ืขื‘ื•ื“ื” ืขื MS SQL ืž- Powershell ืขืœ ืœื™ื ื•ืงืก

ืžืืžืจ ื–ื” ื”ื•ื ืคืจืงื˜ื™ ื‘ืœื‘ื“ ื•ืžื•ืงื“ืฉ ืœืกื™ืคื•ืจ ื”ืขืฆื•ื‘ ืฉืœื™

ืžืชื›ื•ื ืŸ ืœ Zero Touch PROD ืขื‘ื•ืจ RDS (MS SQL), ืฉืœื’ื‘ื™ื• ื›ืœ ื”ืื•ื–ื ื™ื™ื ืžื–ืžื–ืžื•, ื”ื›ื ืชื™ ืžืฆื’ืช (POC - Proof Of Concept) ืฉืœ ืื•ื˜ื•ืžืฆื™ื”: ืกื˜ ืฉืœ ืกืงืจื™ืคื˜ื™ื ืฉืœ Powershell. ืœืื—ืจ ื”ืžืฆื’ืช, ื›ืฉืžื—ื™ืื•ืช ื”ื›ืคื™ื™ื ื”ืกื•ืขืจื•ืช ื•ื”ืžืžื•ืฉื›ื•ืช ื“ืขื›ื•, ื•ื”ืคื›ื• ืœืžื—ื™ืื•ืช ื›ืคื™ื™ื ื‘ืœืชื™ ืคื•ืกืงื•ืช, ืืžืจื• ืœื™ - ื›ืœ ื–ื” ื˜ื•ื‘, ืื‘ืœ ืจืง ืžืกื™ื‘ื•ืช ืื™ื“ื™ืื•ืœื•ื’ื™ื•ืช, ื›ืœ ืขื‘ื“ื™ ื”ื’'ื ืงื™ื ืก ืฉืœื ื• ืขื•ื‘ื“ื™ื ืขืœ ืœื™ื ื•ืงืก!

ื”ืื ื–ื” ืืคืฉืจื™? ืœืงื—ืช DBA ื›ืœ ื›ืš ื—ื ื•ืžื ื•ืจื” ืžืชื—ืช ืœ-Windows ื•ืœื”ื“ื‘ื™ืง ืื•ืชื• ื‘ื—ื•ื ืฉืœ Powershell ืชื—ืช ืœื™ื ื•ืงืก? ื–ื” ืœื ืื›ื–ืจื™?

ืขื‘ื•ื“ื” ืขื MS SQL ืž- Powershell ืขืœ ืœื™ื ื•ืงืก
ื”ื™ื™ืชื™ ืฆืจื™ืš ืœืฉืงื•ืข ื‘ืฉื™ืœื•ื‘ ื”ืžื•ื–ืจ ื”ื–ื” ืฉืœ ื˜ื›ื ื•ืœื•ื’ื™ื•ืช. ื›ืžื•ื‘ืŸ, ื›ืœ 30+ ื”ืกืงืจื™ืคื˜ื™ื ืฉืœื™ ื”ืคืกื™ืงื• ืœืขื‘ื•ื“. ืœื”ืคืชืขืชื™, ื”ืฆืœื—ืชื™ ืœืชืงืŸ ื”ื›ืœ ื‘ื™ื•ื ืขื‘ื•ื“ื” ืื—ื“. ืื ื™ ื›ื•ืชื‘ ื‘ืžืจื“ืฃ ืœื•ื”ื˜. ืื– ื‘ืื™ืœื• ืžืœื›ื•ื“ื•ืช ืืชื” ื™ื›ื•ืœ ืœื”ื™ืชืงืœ ื‘ืขืช ื”ืขื‘ืจืช ืกืงืจื™ืคื˜ื™ื ืฉืœ Powershell ืž-Windows ืœืœื™ื ื•ืงืก?

sqlcmd ืœืขื•ืžืช Invoke-SqlCmd

ื”ืจืฉื• ืœื™ ืœื”ื–ื›ื™ืจ ืœื›ื ืืช ื”ื”ื‘ื“ืœ ื”ืขื™ืงืจื™ ื‘ื™ื ื™ื”ื. ืฉื™ืจื•ืช ื™ืฉืŸ ื•ื˜ื•ื‘ sqlcmd ื–ื” ืขื•ื‘ื“ ื’ื ืชื—ืช ืœื™ื ื•ืงืก, ืขื ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ื›ืžืขื˜ ื–ื”ื”. ืื ื• ืžืขื‘ื™ืจื™ื ืืช ื”ืฉืื™ืœืชื” ืœื‘ื™ืฆื•ืข -Q, ืงื•ื‘ืฅ ื”ืงืœื˜ ื›-i, ื•ื”ืคืœื˜ ื›-o. ืื‘ืœ ืฉืžื•ืช ื”ืงื‘ืฆื™ื, ื›ืžื•ื‘ืŸ, ื ืขืฉื™ื ืชืœื•ื™ื™-ืจื™ืฉื™ื•ืช. ืื ืืชื” ืžืฉืชืžืฉ ื‘-i, ืื– ื‘ืงื•ื‘ืฅ ื›ืชื•ื‘ ื‘ืกื•ืฃ:

GO
EXIT

ืื ืื™ืŸ EXIT ื‘ืกื•ืฃ, ืื– sqlcmd ื™ืžืฉื™ืš ืœื”ืžืชื™ืŸ ืœืงืœื˜, ื•ืื ืœืคื ื™ ื™ึฐืฆึดื™ืึธื” ืœื GO, ืื– ื”ืคืงื•ื“ื” ื”ืื—ืจื•ื ื” ืœื ืชืขื‘ื•ื“. ืงื•ื‘ืฅ ื”ืคืœื˜ ืžื›ื™ืœ ืืช ื›ืœ ื”ืคืœื˜, ื”ื‘ื—ื™ืจื•ืช, ื”ื”ื•ื“ืขื•ืช, ื”ื”ื“ืคืกื” ื•ื›ื•'.

Invoke-SqlCmd ืžื™ื™ืฆืจ ืืช ื”ืชื•ืฆืื” ื›-DataSet, DataTables ืื• DataRows. ืœื›ืŸ, ืื ืืชื” ืžืขื‘ื“ ืืช ื”ืชื•ืฆืื” ืฉืœ ื‘ื—ื™ืจื” ืคืฉื•ื˜ื”, ืืชื” ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ sqlcmd, ืœืื—ืจ ืฉื ื™ืชื— ืืช ื”ืคืœื˜ ืฉืœื•, ื–ื” ื›ืžืขื˜ ื‘ืœืชื™ ืืคืฉืจื™ ืœื’ื–ื•ืจ ืžืฉื”ื• ืžื•ืจื›ื‘: ื‘ืฉื‘ื™ืœ ื–ื” ื™ืฉ Invoke-SqlCmd. ืื‘ืœ ืœืฆื•ื•ืช ื”ื–ื” ื™ืฉ ื’ื ื‘ื“ื™ื—ื•ืช ืžืฉืœื•:

  • ืื ืชืขื‘ื™ืจ ืœื” ืงื•ื‘ืฅ ื‘ืืžืฆืขื•ืช -InputFile, ืื– ื™ึฐืฆึดื™ืึธื” ืื™ืŸ ืฆื•ืจืš, ื™ืชืจ ืขืœ ื›ืŸ, ื”ื•ื ืžื™ื™ืฆืจ ืฉื’ื™ืืช ืชื—ื‘ื™ืจ
  • -ืงื•ื‘ืฅ ืคืœื˜ ืœื, ื”ืคืงื•ื“ื” ืžื—ื–ื™ืจื” ืœืš ืืช ื”ืชื•ืฆืื” ื›ืื•ื‘ื™ื™ืงื˜
  • ื™ืฉื ื ืฉื ื™ ืชื—ื‘ื™ืจื™ื ืœืฆื™ื•ืŸ ืฉืจืช: -ServerInstance - ืฉื ืžืฉืชืžืฉ - ืกื™ืกืžื” - ืžืกื“ ื ืชื•ื ื™ื ื•ื“ืจืš -ืžื—ืจื•ื–ืช ื—ื™ื‘ื•ืจ. ื‘ืื•ืคืŸ ืžื•ื–ืจ, ื‘ืžืงืจื” ื”ืจืืฉื•ืŸ ืœื ื ื™ืชืŸ ืœืฆื™ื™ืŸ ื™ืฆื™ืื” ืื—ืจืช ืžืืฉืจ 1433.
  • ืคืœื˜ ื˜ืงืกื˜, ื”ืงืœื“ PRINT, ืฉืคืฉื•ื˜ "ื ืชืคืก" sqlcmdืขื‘ื•ืจ Invoke-SqlCmd ืžื”ื•ื•ื” ื‘ืขื™ื”
  • ื•ื”ื›ื™ ื—ืฉื•ื‘: ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉืื™ืŸ ืœืœื™ื ื•ืงืก ืฉืœืš ืืช ื”-cmdlet ื”ื–ื”!

ื•ื–ื• ื”ื‘ืขื™ื” ื”ืขื™ืงืจื™ืช. ืจืง ื‘ืžืจืฅ ื”-cmdlet ื”ื–ื” ื”ืคืš ื–ืžื™ืŸ ืขื‘ื•ืจ ืคืœื˜ืคื•ืจืžื•ืช ืฉืื™ื ืŸ Windows, ื•ืกื•ืฃ ืกื•ืฃ ื ื•ื›ืœ ืœื”ืชืงื“ื!

ื”ื—ืœืคื” ืžืฉืชื ื”

ืœ-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)

ืื– ื”ื ื” ื–ื”. ื‘-*nix ื”ื—ืœืคื•ืช ืžืฉืชื ื•ืช ืœื ืขื•ื‘ื“ื•ืช... ืคึผึธืจึธืžึถื˜ึถืจ -v ื”ืชืขืœืžื•. U Invoke-SqlCmd ื”ืชืขืœืžื• -ืžืฉืชื ื™ื. ืœืžืจื•ืช ืฉืžืชืขืœืžื™ื ืžื”ืคืจืžื˜ืจ ืฉืžืฆื™ื™ืŸ ืืช ื”ืžืฉืชื ื™ื ืขืฆืžื, ื”ื”ื—ืœืคื•ืช ืขืฆืžืŸ ืคื•ืขืœื•ืช - ืืชื” ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ื›ืœ ืžืฉืชื ื™ื ืž-Shell. ืขื ื–ืืช, ื ืขืœื‘ืชื™ ืžื”ืžืฉืชื ื™ื ื•ื”ื—ืœื˜ืชื™ ืœื ืœืกืžื•ืš ืขืœื™ื”ื ื›ืœืœ, ื•ืคืขืœืชื™ ื‘ื’ืกื•ืช ื•ืคืจื™ืžื™ื˜ื™ื‘ื™ืช, ืžื›ื™ื•ื•ืŸ ืฉื”ืกืงืจื™ืคื˜ื™ื ืฉืœ 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"

ื–ื”, ื›ืคื™ ืฉืืชื” ืžื‘ื™ืŸ, ืžื‘ื—ืŸ ื›ื‘ืจ ืžื’ืจืกืช ื™ื•ื ื™ืงืก.

ื”ืขืœื” ืงื‘ืฆื™ื

ื‘ื’ืจืกืช Windows ื›ืœ ืคืขื•ืœื” ืœื•ื•ืชื” ื‘ื‘ื™ืงื•ืจืช: ื”ืจืฆื ื• 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() 
  }  

ื›ื“ื™ ืœื‘ื—ื•ืจ ืชื•ื›ืŸ, ืขืœื™ืš ืœื‘ื—ื•ืจ ืœืคื™ ืžื–ื”ื”, ื‘ื—ื™ืจื” ื‘ืกื“ืจ n (ื–ื”ื•ืช).

ื‘ืžืืžืจ ื”ื‘ื ืืคืจื˜ ื™ื•ืชืจ ืขืœ ื”ืื•ืคืŸ ืฉื‘ื• ื›ืœ ื–ื” ืžืชืงืฉืจ ืขื ื’'ื ืงื™ื ืก.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”