Nggarap MS SQL saka Powershell ing Linux

Artikel iki murni praktis lan khusus kanggo crita sedihku

Siap-siap kanggo PROD Tutul Zero kanggo RDS (MS SQL), bab kang kabeh kuping kita padha buzzing, Aku nggawe presentation (POC - Proof Of Concept) automation: pesawat saka skrip powershell. Sawise presentation, nalika badai, keplok ingkang dipun danguaken mati mudhun, ngowahi menyang incessant keplok, padha marang kula - kabeh iki apik, nanging mung kanggo alasan ideologi, kabeh budak Jenkins kita makarya ing Linux!

Apa iki bisa? Njupuk DBA anget, lampu saka ing Windows lan kelet ing panas banget saka powershell ing Linux? Apa ora iki kejem?

Nggarap MS SQL saka Powershell ing Linux
Aku kudu nyemplungaken dhewe ing kombinasi aneh iki teknologi. Mesthi, kabeh 30+ skrip saya mandheg. Kanggo kaget, aku bisa ndandani kabeh ing sawijining dina kerja. Aku nulis ing nguber panas. Dadi, pitfalls apa sing bisa sampeyan temoni nalika nransfer skrip powershell saka Windows menyang Linux?

sqlcmd vs Invoke-SqlCmd

Ayo kula ngelingake sampeyan prabΓ©dan utama ing antarane. Utilitas lawas sing apik sqlcmd Uga dianggo ing Linux, kanthi fungsi sing meh padha. We pass query kanggo nglakokakΓ© -Q, file input minangka -i, lan output minangka -o. Nanging jeneng file, mesthi, digawe cilik-sensitif. Yen sampeyan nggunakake -i, banjur ing file tulis ing pungkasan:

GO
EXIT

Yen ora ana EXIT ing pungkasan, sqlcmd bakal nerusake ngenteni input, lan yen sadurunge MUTU ЅЅ¡¡ Β± Β± Β± GO, banjur printah pungkasan ora bakal bisa. File output ngemot kabeh output, pilih, pesen, print, etc.

Invoke-SqlCmd ngasilake asil minangka DataSet, DataTables utawa DataRows. Mulane, yen sampeyan ngolah asil saka pilihan prasaja, sampeyan bisa nggunakake sqlcmd, Duwe parsed sawijining output, iku meh mokal kanggo niru soko Komplek: kanggo iki ana Invoke-SqlCmd. Nanging tim iki uga duwe lelucon dhewe:

  • Yen sampeyan nransfer file menyang dheweke liwat -InputFile, banjur MUTU ora perlu, malih, iku mrodhuksi kesalahan sintaksis
  • -OutputFile ora, printah ngasilake asil minangka obyek
  • Ana rong sintaksis kanggo nemtokake server: -ServerInstance -Jeneng pangguna -Sandi -Database lan liwat -KoneksiString. Cukup aneh, ing kasus sing sepisanan ora bisa nemtokake port liyane saka 1433.
  • output teks, ketik PRINT, sing mung "dicekel" sqlcmdkanggo Invoke-SqlCmd iku masalah
  • Lan sing paling penting: Kemungkinan Linux sampeyan ora duwe cmdlet iki!

Lan iki masalah utama. Mung ing Maret cmdlet iki kasedhiya kanggo platform non-Windows, lan pungkasane kita bisa maju!

Substitusi variabel

sqlcmd nduweni substitusi variabel nggunakake -v, contone kaya iki:

# $conn содСрТит Π½Π°Ρ‡Π°Π»ΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ sqlcmd
$cmd = $conn + " -i D:appsSlaveJobsKillSpid.sql -o killspid.res 
  -v spid =`"" + $spid + "`" -v age =`"" + $age + "`""
Invoke-Expression $cmd

Ing skrip SQL kita nggunakake substitusi:

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

Dadi ing kene. Ing *nix substitusi variabel ora bisa... Parameter -v digatekake. U Invoke-SqlCmd digatekake -Variabel. Sanajan parameter sing nemtokake variabel dhewe ora digatekake, substitusi dhewe bisa digunakake-sampeyan bisa nggunakake variabel apa wae saka Shell. Nanging, aku gelo karo variabel kasebut lan mutusake ora gumantung ing kabeh, lan tumindak kasar lan primitif, amarga skrip SQL cendhak:

# 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"

Iki, kaya sing sampeyan ngerteni, minangka tes saka versi Unix.

Ngunggah file

Ing versi Windows, operasi apa wae sing diiringi audit: kita mlayu sqlcmd, nampa sawetara jenis penyalahgunaan ing file output, ditempelake file iki menyang piring audit. Untunge, server SQL makarya ing server sing padha karo Jenkins, wis rampung kaya mangkene:

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

Mangkono, kita ngulu file BCP tanggung lan shove menyang nvarchar(max) lapangan ing meja audit. Mesthine, kabeh sistem iki ambruk, amarga tinimbang server SQL aku entuk RDS, lan BULK INSERT ora bisa digunakake liwat UNC amarga nyoba njupuk kunci eksklusif ing file, lan kanthi RDS iki umume ditakoni. wiwitan banget. Dadi aku mutusake kanggo ngganti desain sistem, nyimpen baris audit kanthi baris:

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

Lan nulis ing tabel iki kaya mangkene:

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() 
  }  

Kanggo milih isi, sampeyan kudu milih miturut ID, milih ing urutan n (identitas).

Ing artikel sabanjure aku bakal luwih rinci babagan carane kabeh iki sesambungan karo Jenkins.

Source: www.habr.com

Add a comment