Gawe sareng MS SQL ti Powershell on Linux

Tulisan ieu murni praktis sareng dikhususkeun pikeun carita sedih kuring

Nyiapkeun pikeun Nol Toél PROD pikeun RDS (MS SQL), ngeunaan nu sagala Ceuli urang buzzing, abdi ngadamel presentasi (POC - Buktina Konsep) automation: susunan Aksara Powershell. Saatos presentasi, nalika ribut, keprok berkepanjangan maot turun, ngarobah kana keprok incessant, aranjeunna ngawartoskeun kuring - kabeh ieu alus, tapi ngan pikeun alesan ideologis, sadaya budak Jenkins urang dianggo dina Linux Ubuntu!

Ieu mungkin? Candak lampu DBA anu haneut sapertos dina Windows sareng lengket dina panas pisan tina Powershell dina Linux? Ieu teu kejem?

Gawe sareng MS SQL ti Powershell on Linux
Kuring kedah neuleumkeun diri dina kombinasi téknologi aneh ieu. Tangtosna, sadaya 30+ naskah kuring lirén damel. Pikeun reuwas kuring, kuring junun ngalereskeun sagalana dina hiji poé gawé. Kuring keur nulis dina ngungudag panas. Janten, pitfalls naon anu anjeun tiasa mendakan nalika nransferkeun skrip powerhell tina Windows ka Linux?

sqlcmd vs Invoke-SqlCmd

Hayu atuh ngingetan ngeunaan bédana utama antara aranjeunna. Utiliti heubeul alus sqlcmd Éta ogé dianggo dina Linux, kalayan fungsionalitas anu ampir sami. Urang lulus query pikeun ngaéksekusi -Q, file input salaku -i, sarta kaluaran salaku -o. Tapi ngaran file, tangtosna, dijieun case-sénsitip. Upami anjeun nganggo -i, teras dina file nyerat dina tungtungna:

GO
EXIT

Upami teu aya EXIT dina tungtungna, sqlcmd bakal teras ngantosan input, sareng upami sateuacan KALUAR moal GO, teras paréntah anu terakhir moal jalan. Berkas kaluaran ngandung sadaya kaluaran, pilih, pesen, citak, jsb.

Invoke-SqlCmd ngahasilkeun hasil salaku DataSet, DataTables atanapi DataRows. Ku alatan éta, lamun ngolah hasil tina pilihan basajan, Anjeun bisa make sqlcmd, sanggeus parsed kaluaran na, ampir teu mungkin keur diturunkeun hal kompléks: keur ieu aya Nelepon-SqlCmd. Tapi tim ieu ogé gaduh guyonan sorangan:

  • Lamun mindahkeun file ka dirina via - InputFileterus KALUAR teu diperlukeun, komo deui, eta ngahasilkeun kasalahan sintaksis
  • -OutputFile teu, paréntah mulih maneh hasil salaku obyék
  • Aya dua sintaksis pikeun nangtukeun server: -ServerInstance -Username -Password -Database sarta ngaliwatan -ConnectionString. Cukup Oddly, dina kasus nu pertama teu mungkin pikeun nangtukeun port lian ti 1433.
  • kaluaran téks, ngetik PRINT, nu ngan saukur "bray" sqlcmdpikeun Nelepon-SqlCmd mangrupa masalah
  • Sareng anu paling penting: Paling dipikaresep Linux Anjeun teu boga cmdlet ieu!

Sareng ieu mangrupikeun masalah utama. Ngan dina Maret cmdlet ieu janten sadia pikeun platform non-Windows, sarta tungtungna urang bisa maju!

Substitusi Variabel

sqlcmd gaduh substitusi variabel nganggo -v, contona sapertos kieu:

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

Dina skrip SQL kami nganggo substitusi:

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

Tah di dieu. Dina *nix substitusi variabel teu jalan. Parameter -v teu dipaliré. U Nelepon-SqlCmd teu dipaliré -Variabel. Sanajan parameter nu nangtukeun variabel sorangan teu dipaliré, substitusi sorangan jalan-anjeun tiasa make variabel sagala ti Shell. Nanging, kuring gelo ku variabel-variabel sareng mutuskeun henteu ngandelkeun aranjeunna sadayana, sareng ngalaksanakeun kasar sareng primitif, sabab skrip SQL pondok:

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

Ieu, sakumaha anu anjeun ngartos, mangrupikeun tés tina versi Unix.

Ngunggah file

Dina versi Windows, sagala operasi ieu dibarengan ku hiji Inok: urang ngajalankeun sqlcmd, narima sababaraha jenis nyiksa dina file output, napel file ieu piring Inok. Untungna, pangladén SQL damel dina server anu sami sareng Jenkins, éta dilakukeun sapertos kieu:

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

Ku kituna, urang ngelek file BCP sagemblengna tur nyorong kana nvarchar(max) widang tabel Inok. Tangtosna, sadayana sistem ieu ambruk, sabab tinimbang server SQL kuring ngagaduhan RDS, sareng INSERT BULK henteu jalan pisan via UNC kusabab usaha nyandak konci ekslusif dina file, sareng RDS ieu umumna ditakdirkeun. mimiti pisan. Janten kuring mutuskeun pikeun ngarobih desain sistem, nyimpen garis Inok ku garis:

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

Jeung nulis dina tabel ieu kawas kieu:

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

Pikeun milih eusi, Anjeun kudu milih ku ID, milih dina urutan n (identitas).

Dina artikel salajengna kuring bakal langkung rinci ngeunaan kumaha ieu sadayana berinteraksi sareng Jenkins.

sumber: www.habr.com

Tambahkeun komentar