په لینکس کې د پاورشیل څخه د MS SQL سره کار کول

دا مقاله خالصه عملي ده او زما غمجنې کیسې ته وقف شوې ده

لپاره چمتو کول د صفر ټچ پروډ د RDS (MS SQL) لپاره، چې په اړه یې زموږ ټول غوږونه ګونګ وو، ما د اتوماتیک پریزنټشن (POC - د مفهوم ثبوت) جوړ کړ: د پاورشیل سکریپټونو سیټ. د پریزنټشن وروسته ، کله چې طوفاني ، اوږده ستاینه مړه شوه ، په پرله پسې تالیو بدله شوه ، دوی ماته وویل - دا ټول ښه دي ، مګر یوازې د ایډیالوژیکي دلایلو لپاره ، زموږ ټول جینکنز غلامان په لینکس کې کار کوي!

ایا دا ممکنه ده؟ د وینډوز لاندې څخه دومره ګرم ، څراغ DBA واخلئ او د لینکس لاندې د پاورشیل خورا ګرمۍ کې یې وخورئ؟ دا ظلم نه دی؟

په لینکس کې د پاورشیل څخه د MS SQL سره کار کول
زه باید ځان د ټیکنالوژیو په دې عجیب ترکیب کې ډوب کړم. البته، زما ټول 30+ سکریپټونه کار کول بند کړل. زما د حیرانتیا لپاره، ما په یوه کاري ورځ کې هرڅه سم کړل. زه په ګرم تعقیب کې لیکم. نو، د وینډوز څخه لینوکس ته د پاورشیل سکریپټونو لیږدولو په وخت کې تاسو له کوم زیانونو سره مخ کیدی شئ؟

sqlcmd vs invoke-SqlCmd

اجازه راکړئ تاسو ته د دوی تر مینځ اصلي توپیر یادونه وکړم. ښه زوړ افادیت sqlcmd دا د لینکس لاندې هم کار کوي، نږدې ورته فعالیت سره. موږ د -Q د اجرا کولو لپاره پوښتنه پاس کوو، د ان پټ فایل د -i په توګه او آوټ پوټ د -o په توګه. مګر د فایل نومونه، البته، د قضیې حساس شوي دي. که تاسو -i کاروئ، نو په فایل کې په پای کې ولیکئ:

GO
EXIT

که په پای کې EXIT شتون ونلري، نو sqlcmd به د ننوتلو انتظار ته لاړ شي، او که مخکې وتون نه به GO، نو وروستی کمانډ به کار ونکړي. د محصول فایل ټول محصول لري، انتخابونه، پیغامونه، چاپ، او نور.

Invoke-SqlCmd پایله د ډیټا سیټ ، ډیټا میزونو یا ډیټا رایو په توګه تولیدوي. له همدې امله ، که تاسو د ساده انتخاب پایله پروسس کوئ ، تاسو یې کارولی شئ sqlcmdد خپل محصول تحلیل کولو سره، دا تقریبا ناممکن دی چې یو څه پیچلي ترلاسه کړي: د دې لپاره شتون لري Invoke-SqlCmd. مګر دا ټیم هم خپل ټوکې لري:

  • که تاسو د هغې له لارې هغې ته فایل لیږدئ - د انپټ فایلبیا وروسته وتون اړتیا نشته، سربیره پردې، دا د نحوي تېروتنه رامنځته کوي
  • - د آوټ پټ فایل نه، کمانډ تاسو ته د اعتراض په توګه پایله درکوي
  • د سرور مشخص کولو لپاره دوه ترکیبونه شتون لري: -ServerInstance - کارن نوم - پټنوم - ډیټابیس او له لارې - 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)

نو دلته دی. په *نکس متغیر بدیلونه کار نه کوي. پیرامیټر -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

Add a comment