【问题标题】:Dynamic SQL Server query动态 SQL Server 查询
【发布时间】:2017-01-11 19:55:23
【问题描述】:

我正在存储过程中编写动态插入查询。我正在接收列名作为我的存储过程的参数。

例如,我有一个 Employee 表,其中包含 EmployeeIdEmployeeName 列。我需要在每个员工姓名之前附加EMP_,同时将数据从Employee 表插入到Department 表中。

非动态查询如下所示。

 INSERT INTO Department(EmployeeId, EmployeeName)
     SELECT 
         EmployeeId, 'EMP_' + EmployeeName
     FROM 
         Employee

如果我写一个动态插入

 SET @SqlCommand =
          'INSERT INTO ' + @DepartmentTable + '(' + @EmployeeIdColumn + ',' + @EmployeeNameColumn + ')' +
          'SELECT ' + @EmployeeIdColumn + ',''EMP_''' + @EmployeeNameColumn + '''' +     
          'FROM ' +
              @EmployeeTable + ' WTB '  

        EXEC sp_executesql
        @stmt        = @SqlCommand 

问题在于,对于 EmployeeName 列,它插入的是“EMP_EmployeeName”而不是实际的员工姓名。我尝试在EmployeeNameColumn 前后加上引号,但没有成功。我该如何解决?

【问题讨论】:

  • 在每个员工姓名前附加“EMP”。 @EmployeeNameColumn 是存储过程接收的列名。
  • 虽然这不是并且预先回答,但我强烈建议您阅读这篇博文。每当我在做动态 sql 时,我都会参考它。它详细介绍了许多实现动态 sql 的“最佳实践”方法,既安全(参数化)又高效sommarskog.se/dynamic_sql.html#good_practices
  • @turbo88 嘿!您是否尝试过提供的任何解决方案?

标签: sql sql-server tsql dynamic-sql


【解决方案1】:

EMP_'' 之后只需要一个+,并在' WTB ' 之后删除它。我还修复了一些空格:

SET @SqlCommand =
'INSERT INTO ' + @DepartmentTable + ' (' + @EmployeeIdColumn + ',' + @EmployeeNameColumn + ')' +
' SELECT ' + @EmployeeIdColumn + ',''EMP_''+' + @EmployeeNameColumn +      
' FROM ' + @EmployeeTable + ' WTB ' 

如果你PRINT @SqlCommand 你会得到这样的东西:

INSERT INTO Department (EmpId,EmpName) SELECT EmpId,'EMP_'+EmpName FROM Employee WTB 

还有一点:最好将QUOTENAME 与表/列名称一起使用。这将有助于避免列名称中包含空格的情况,例如“员工姓名”:

SET @SqlCommand =
'INSERT INTO ' + QUOTENAME(@DepartmentTable) + '(' + QUOTENAME(@EmployeeIdColumn) + ',' + QUOTENAME(@EmployeeNameColumn) + ')'+
' SELECT ' + QUOTENAME(@EmployeeIdColumn) + ',''EMP_''+' + QUOTENAME(@EmployeeNameColumn) + 
' FROM ' + QUOTENAME(@EmployeeTable) + ' WTB '

获得:

INSERT INTO [Department]([EmpId],[EmpName]) SELECT [EmpId],'EMP_'+[EmpName] FROM [Employee] WTB 

【讨论】:

    【解决方案2】:

    尝试使用CONCAT 函数。

    -- Syntax for SQL Server, Azure SQL Database, Azure SQL Data Warehouse, Parallel Data Warehouse  
    
    CONCAT ( string_value1, string_value2 [, string_valueN ] )  
    

    您的查询将如下所示:

    INSERT INTO deptTable(empId,empName) 
    SELECT empId,concat('EMP_', empName) as empName FROM empTable
    

    PS:看来我误解了你的问题。

    INSERT INTO deptTable(empId,empName) 
    SELECT empId,'SUFFIX'+empName as empName FROM empTable
    

    也可以。我猜你想要它用于存储过程。

    无论如何,concat 仍然应该这样做。

    【讨论】:

      【解决方案3】:

      这是使用带有列和参数的insert 语句创建存储过程的动态查询

      > DECLARE @table_name varchar(255) = 'table_name'
      >       DECLARE @v_col varchar(MAX)
      >       DECLARE @v_param varchar(MAX)
      >       DECLARE @SP_param varchar(MAX)
      >       DECLARE @sp_type varchar(10) = 'Insert'
      >     
      >         SET @v_col = STUFF(
      >                      (SELECT ',' + '['+c.name+']'
      >                      FROM sys.tables t  JOIN sys.columns c ON t.object_id = c.object_id
      >                                 WHERE t.name = @table_name
      >                                 AND c.is_identity = 0
      >                          FOR XML PATH ('')), 1, 1, ''
      >                             )
      >         SET @v_param =  STUFF(
      >                          (SELECT ',' + '@'+c.name
      >                          FROM sys.tables t  JOIN sys.columns c ON t.object_id = c.object_id
      >                                 WHERE t.name = @table_name
      >                                 AND c.is_identity = 0
      >                          FOR XML PATH ('')), 1, 1, ''
      >                             )
      >     
      >         SET @SP_param = STUFF(
      >                          (SELECT ',' + '@'+c.name+' '+y.name+' '+(CASE WHEN y.name = 'varchar' THEN '('+CAST(c.max_length as varchar)+')'
      > ELSE '' END)
      >                          FROM sys.tables t  JOIN sys.columns c ON t.object_id = c.object_id
      >                          JOIN sys.types y ON y.user_type_id = c.user_type_id
      >                                 WHERE t.name = @table_name
      >                                 AND c.is_identity = 0
      >                          FOR XML PATH ('')), 1, 1, ''
      >                             )
      >       Declare @Query VARCHAR(MAX)
      >       DECLARE @SPQuery VARCHAR(MAX)
      >       SET @SPQuery = 'CREATE PROCEDURE '+@sp_type+''+@table_name+' ('+@SP_param+')
      >       AS BEGIN'
      >       SET @Query='Insert Into '+@table_name+' ('+@v_col+')
      >         Values (
      >             '+@v_param+')
      >             END'
      >     
      >     
      >       PRINT(@SPQuery); 
      >       PRINT(@Query);
      

      【讨论】:

        猜你喜欢
        • 2010-09-20
        • 2012-05-11
        相关资源
        最近更新 更多