Linux تي Powershell کان MS SQL سان ڪم ڪرڻ

هي مضمون خالص عملي آهي ۽ منهنجي اداس ڪهاڻي لاء وقف آهي

لاء تيار ٿيڻ زيرو ٽچ PROD RDS (MS SQL) لاءِ، جنهن بابت اسان جا سڀئي ڪن گونجندا هئا، مون آٽوميشن جي هڪ پريزنٽيشن (POC - Proof of Concept) ڪئي: پاور شيل اسڪرپٽ جو هڪ سيٽ. پريزنٽيشن کان پوءِ، جڏهن طوفاني، ڊگھي تاليون ختم ٿي ويون، مسلسل تاڙيون وڄائڻ ۾، هنن مون کي ٻڌايو - اهو سڀ ڪجهه سٺو آهي، پر صرف نظرياتي سببن جي ڪري، اسان جا سڀئي جينڪن غلام لينڪس تي ڪم ڪن ٿا!

ڇا اهو ممڪن آهي؟ ونڊوز جي ھيٺان ھڪڙو گرم، چراغ ڊي بي اي وٺو ۽ ان کي لينڪس جي ھيٺان پاور شيل جي تمام گرمي ۾ لٺ ڪريو؟ ڇا هي ظلم ناهي؟

Linux تي Powershell کان MS SQL سان ڪم ڪرڻ
مون کي ٽيڪنالاجي جي هن عجيب ميلاپ ۾ پاڻ کي وسارڻو پيو. يقينن، منهنجي سڀني 30+ اسڪرپٽ ڪم ڪرڻ بند ڪيو. منهنجي تعجب ۾، مون هڪ ڪم ڪندڙ ڏينهن ۾ هر شي کي درست ڪرڻ ۾ مدد ڪئي. مان گرم تعاقب ۾ لکي رهيو آهيان. تنهن ڪري، ونڊوز کان لينڪس تائين پاور شيل اسڪرپٽ منتقل ڪرڻ وقت توهان ڪهڙي نقصان سان منهن ڏئي سگهو ٿا؟

sqlcmd vs invoke-SqlCmd

اچو ته توهان کي انهن جي وچ ۾ بنيادي فرق جي ياد ڏياري. سٺي پراڻي افاديت sqlcmd اهو پڻ لينڪس جي تحت ڪم ڪري ٿو، تقريبن هڪجهڙائي واري ڪارڪردگي سان. اسان -Q تي عمل ڪرڻ لاءِ سوال پاس ڪريون ٿا، ان پٽ فائل کي -i، ۽ آئوٽ پٽ کي -o. پر فائل جا نالا، يقينا، ڪيس-حساس ڪيا ويا آهن. جيڪڏھن توھان استعمال ڪريو -i، پوء فائل ۾ آخر ۾ لکو:

GO
EXIT

جيڪڏهن آخر ۾ ڪو به EXIT نه آهي، پوء sqlcmd ان پٽ جي انتظار ۾ اڳتي وڌندو، ۽ جيڪڏهن اڳ نڪرڻ نه ٿيندو GO، پوءِ آخري حڪم ڪم نه ڪندو. ٻاھرين فائل ۾ سڀ آئوٽ، چونڊ، پيغام، پرنٽ وغيره شامل آھن.

Invoke-SqlCmd نتيجو پيدا ڪري ٿو DataSet، DataTables يا DataRows. تنهن ڪري، جيڪڏهن توهان هڪ سادي چونڊ جو نتيجو پروسيس ڪيو، توهان استعمال ڪري سگهو ٿا sqlcmd, ان جي پيداوار کي پارس ڪرڻ کان پوء، اهو لڳ ڀڳ ناممڪن آهي ته ڪجهه پيچيده حاصل ڪرڻ لاء: هن لاء آهي Invoke-SqlCmd. پر هن ٽيم کي پڻ پنهنجو مذاق آهي:

  • جيڪڏهن توهان ان جي ذريعي هڪ فائل منتقل ڪيو -انپٽ فائل، پوء نڪرڻ ضرورت ناهي، ان کان علاوه، اهو هڪ نحو جي غلطي پيدا ڪري ٿو
  • -OutputFile نه، حڪم توهان کي نتيجو ڏئي ٿو هڪ اعتراض جي طور تي
  • سرور جي وضاحت ڪرڻ لاءِ ٻه نحو آهن: -ServerInstance -Username -Password -Database ۽ ذريعي -ConnectionString. حيرت انگيز طور تي، پهرين صورت ۾ اهو ممڪن ناهي ته 1433 کان سواء ٻيو ڪو بندرگاهه بيان ڪيو وڃي.
  • ٽيڪسٽ آئوٽ، ٽائپ ڪريو PRINT، جيڪو صرف "پکڙيل" آهي sqlcmdلاء Invoke-SqlCmd هڪ مسئلو آهي
  • ۽ سڀ کان اهم: گهڻو ڪري توهان جي لينڪس وٽ هي cmdlet نه آهي!

۽ اهو بنيادي مسئلو آهي. صرف مارچ ۾ هن cmdlet غير ونڊوز پليٽ فارمن لاءِ دستياب ٿيو، ۽ آخرڪار اسان اڳتي وڌي سگهون ٿا!

متغير متبادل

sqlcmd ۾ -v استعمال ڪندي متغير متبادل آھي، مثال طور ھن طرح:

# $conn содержит начало команды sqlcmd
$cmd = $conn + " -i D:appsSlaveJobsKillSpid.sql -o killspid.res 
  -v spid =`"" + $spid + "`" -v age =`"" + $age + "`""
Invoke-Expression $cmd

SQL اسڪرپٽ ۾ اسان متبادل استعمال ڪندا آهيون:

set @spid=$(spid)
set @age=$(age)

سو هتي آهي. * نڪس ۾ variable متبادل ڪم نه ڪندا آھن. پيرا ميٽر -v نظرانداز ڪيو ويو. يو Invoke-SqlCmd نظرانداز ڪيو ويو - متغير. جيتوڻيڪ پيٽرولر جيڪو بيان ڪري ٿو متغير پاڻ کي نظر انداز ڪيو ويو آهي، متبادل پاڻ کي ڪم ڪري ٿو- توهان شيل مان ڪي به متغير استعمال ڪري سگهو ٿا. بهرحال، مون متغيرن کان ناراض ٿي ويو ۽ فيصلو ڪيو ته انهن تي هرگز انحصار نه ڪيو وڃي، ۽ بي رحم ۽ بنيادي طور تي ڪم ڪيو، ڇو ته SQL اسڪرپٽ مختصر آهن:

# prepend the parameters  
"declare @age int, @spid int" | Add-Content "q.sql"
"set @spid=" + $spid | Add-Content "q.sql"
"set @age=" + $age | Add-Content "q.sql"

foreach ($line in Get-Content "Sqlserver/Automation/KillSpid.sql") { 
  $line | Add-Content "q.sql" 
  }
$cmd = "/opt/mssql-tools/bin/" + $conn + " -i q.sql -o res.log"

هي، جيئن توهان سمجھو ٿا، يونڪس ورزن کان اڳ ۾ ئي هڪ امتحان آهي.

فائلون لوڊ ڪندي

ونڊوز ورزن ۾، ڪو به آپريشن آڊٽ سان گڏ هوندو هو: اسان sqlcmd هلائي، آئوٽ پٽ فائل ۾ ڪنهن قسم جو غلط استعمال ڪيو، هن فائل کي آڊٽ پليٽ سان ڳنڍيو. خوش قسمتي سان، SQL سرور ساڳئي سرور تي جينڪنز وانگر ڪم ڪيو، اهو ڪجهه هن طرح ڪيو ويو آهي:

CREATE procedure AuditUpload
  @id int, @filename varchar(256)
as
  set nocount on
  declare @sql varchar(max)

  CREATE TABLE #multi (filer NVARCHAR(MAX))
  set @sql='BULK INSERT #multi FROM '''+@filename
    +''' WITH (ROWTERMINATOR = '' '',CODEPAGE = ''ACP'')'
  exec (@sql)
  select @sql=filer from #multi
  update JenkinsAudit set multiliner=@sql where ID=@id
  return

اهڙيء طرح، اسان BCP فائل کي مڪمل طور تي نگلندا آهيون ۽ ان کي آڊٽ ٽيبل جي nvarchar (max) فيلڊ ۾ وڌايو. يقينن، اهو سڄو سسٽم ڌار ٿي ويو، ڇاڪاڻ ته SQL سرور جي بدران مون کي RDS حاصل ڪيو، ۽ BULK INSERT فائل تي هڪ خاص تالا ڪڍڻ جي ڪوشش جي ڪري UNC ذريعي ڪم نٿو ڪري، ۽ RDS سان اهو عام طور تي برباد ٿي ويو آهي. بلڪل شروعات. تنهن ڪري مون سسٽم جي ڊيزائن کي تبديل ڪرڻ جو فيصلو ڪيو، آڊٽ لائن کي لائن ذريعي محفوظ ڪندي:

CREATE TABLE AuditOut (
  ID int NULL,
  TextLine nvarchar(max) NULL,
  n int IDENTITY(1,1) PRIMARY KEY
  )

۽ ھن جدول ۾ ھن طرح لکو:

function WriteAudit([string]$Filename, [string]$ConnStr, 
     [string]$Tabname, [string]$Jobname)
{
  # get $lastid of the last execution  -- проскипано для статьи
	
  #create grid and populate it with data from file
  $audit =  Get-Content $Filename
  $DT = new-object Data.DataTable   

  $COL1 =  new-object Data.DataColumn; 
  $COL1.ColumnName = "ID"; 
  $COL1.DataType =  [System.Type]::GetType("System.Int32") 

  $COL2 =  new-object Data.DataColumn; 
  $COL2.ColumnName = "TextLine"; 
  $COL2.DataType =  [System.Type]::GetType("System.String") 
  
  $DT.Columns.Add($COL1) 
  $DT.Columns.Add($COL2) 
  foreach ($line in $audit) 
    { 
    $DR = $dt.NewRow()   
    $DR.Item("ID") = $lastid
    $DR.Item("TextLine") = $line
    $DT.Rows.Add($DR)   
    } 

  # write it to table
  $conn=new-object System.Data.SqlClient.SQLConnection 
  $conn.ConnectionString = $ConnStr
  $conn.Open() 
  $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnStr
  $bulkCopy.DestinationTableName = $Tabname 
  $bulkCopy.BatchSize = 50000
  $bulkCopy.BulkCopyTimeout = 0
  $bulkCopy.WriteToServer($DT) 
  $conn.Close() 
  }  

مواد کي چونڊڻ لاء، توهان کي ID جي ذريعي چونڊڻ جي ضرورت آهي، ترتيب ۾ چونڊيو (شناخت).

ايندڙ آرٽيڪل ۾ آئون وڌيڪ تفصيل ۾ ويندس ته هي سڀ ڪيئن جينڪنز سان لهه وچڙ ۾ اچي ٿو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو