sql - 变量名称在查询批处理或存储过程中必须是唯一的吗?

标签 sql sql-server powershell t-sql

我们如何在一个事务中运行多个 SQL 脚本,其中每个脚本可能定义相同的变量?

文件1:

declare @tableName varchar(28), @query nvarchar(1000)
set @tableName = '1apples'+convert(varchar(28), getdate(),121)
select @query = 'select name into ' + quotename(@tableName) + ' from sys.objects'
print @query
exec (@query)
go

文件2:

declare @tableName varchar(28), @query nvarchar(1000)
set @tableName = '2apples'+convert(varchar(28), getdate(),121)
select @query = 'select name into ' + quotename(@tableName) + ' from sys.objects'
print @query
exec (@query)
 go

我正在 PowerShell 中执行这样的文件:

try {

  $files = Get-ChildItem -Path $SqlFilesDirectory -File -Filter *.sql
  $filesSorted = $files |Sort-Object -Property Name
  $filesconcatenated = @(
      $files |Get-Content -Raw
  ) -join [Environment]::NewLine
  $filesconcatenated = 'SET XACT_ABORT ON ' + $filesconcatenated + ' SET XACT_ABORT OFF ' + [Environment]::NewLine
    $cmd = New-Object System.Data.SqlClient.SqlCommand ($filesconcatenated), $conn
    $cmd.Transaction = $tran
    [void]$cmd.ExecuteNonQuery()
   
  $tran.Commit()
}
catch {
  $tran.Rollback()
  Write-Host "Record not Inserted ->"
  $_.exception.message
}
finally {
  $conn.Close()
}

我遇到以下异常:

Exception calling "ExecuteNonQuery" with "0" argument(s): "Incorrect syntax near the keyword 'declare'. The variable name '@tableName' has already been declared. Variable names must be unique within a query batch or stored procedure. The variable name '@tableName' has already been declared. Variable names must be unique within a query batch or stored procedure. Incorrect syntax near the keyword 'SET'."

我们如何在一个事务中运行多个 SQL 脚本,其中每个脚本可能定义相同的变量?

这是它尝试运行的完整脚本:

SET XACT_ABORT ON 
declare @tableName varchar(28), @query nvarchar(1000)
set @tableName = '1apples'+convert(varchar(28), getdate(),121)
select @query = 'select name into ' + quotename(@tableName) + ' from sys.objects'
print @query
exec (@query)
go
declare @tableName varchar(28), @query nvarchar(1000)
set @tableName = '2apples'+convert(varchar(28), getdate(),121)
select @query = 'select name into ' + quotename(@tableName) + ' from sys.objects'
print @query
exec (@query)
go
declare @tableName varchar(28), @query nvarchar(1000)
set @tableName = '3apples'+convert(varchar(28), getdate(),121)
select @query = 'select name into ' + quotename(@tableName) + ' from sys.objects'
print @query
exec (@query)
go
 SET XACT_ABORT OFF 

最佳答案

在一个批处理中不能两次使用相同的变量

因此,通过循环数组将它们作为单独的命令执行

$connString = "Server=tcp:$ServerName.database.windows.net,1433;Database=$DBName;User Id=$SvcAdminAccount@$ServerName;Password=$SvcAdminPassword;MultipleActiveResultSets=true;Persist Security Info=true;";
$conn = New-Object System.Data.SqlClient.SqlConnection $connString try
{
  $conn.Open()
  $files = Get-ChildItem -Path $SqlFilesDirectory -File -Filter *.sql
  $filesSorted = $files |Sort-Object -Property Name
  $tran = $conn.BeginTransaction()
  foreach ($file in $filesSorted)
  {
    $query = "SET XACT_ABORT ON; " + (Get-Content -Raw $file)
    $cmd = New-Object System.Data.SqlClient.SqlCommand ($query, $conn, $tran)
    [void]$cmd.ExecuteNonQuery()
  }
  $tran.Commit();
}
catch {
  Write-Host "Record not Inserted ->"
  $_.exception.message
}
finally {
  $tran.Dispose()
  $conn.Dispose()
}

Note the way Dispose is used, rather than Rollback, because Dispose will never throw an exception. It's also in the finally rather than the catch

关于sql - 变量名称在查询批处理或存储过程中必须是唯一的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69789274/

相关文章:

java - 如何使用 jooq 在普通 sql 中使用命名参数

sql - 通过 Oracle SQL 检索范围内的数字

java - jooQ spring boot 多模式(读写分离)

sql-server - 什么是表提示锁的范围?

sql-server - 是否可以以编程方式调用 SQL 触发器?

c# - 有趣的 LinqToSql 行为

mysql - 在 Web UI 中使用 UDF 进行查询

用于监控状态并发送电子邮件结果的 Powershell 脚本

PowerShell DSC 服务缺少成员

powershell - 列出 UNC 根文件夹中的文件夹和文件