0

我需要执行以下存储过程,其中@Table_temp应该连接@Tabletemp。那么我如何正确参数化呢?

CREATE PROCEDURE [dbo].[swap_Collect]
@Table  varchar,
@UniqueColumn varchar
AS

BEGIN
    IF (OBJECT_ID(@Table) IS NOT NULL )
    BEGIN
        DECLARE @Table_temp as varchar 
        SET @Table_temp= @Table + '_temp'
      DELETE FROM @Table where @UniqueColumn in (Select @UniqueColumn from @Table_temp)
      INSERT INTO @Table SELECT * from PRODUCTS_temp
      SELECT 1
    END
ELSE
    BEGIN 
      SELECT * INTO @Table from Collects_temp
      SELECT 1
    END
END

在此处输入图像描述

4

2 回答 2

1
ALTER PROCEDURE [dbo].swap_Collect(
@Table as varchar(MAX),
@UniqueColumn as varchar(MAX))
AS
BEGIN
    IF (OBJECT_ID(@Table) IS NOT NULL )
    BEGIN

       DECLARE @query nvarchar(MAX)
       set @query = 'DELETE FROM '+  @Table + ' where ' + @UniqueColumn  + ' in (Select ' +  @UniqueColumn + ' from ' + @Table +  '_temp)' 
       set @query = @query + 'INSERT INTO ' + @Table + ' SELECT * from ' +  @Table + '_temp'
       EXEC sp_executesql @query
       SELECT 1
    END
    ELSE
    BEGIN 
       set @query = 'SELECT * INTO ' + @Table + ' from ' + @Table + '_temp'
       print @query
       EXEC sp_executesql @query
       SELECT 1
     END
END
于 2020-05-19T21:29:08.683 回答
1

尽管有几种 SQL 方言可以,但 SQL Server 不支持将变量作为对象名称。您必须使用动态 SQL 来解决这个问题。

注释掉这些EXEC行并取消注释这些PRINT行以验证动态 SQL 正在生成适当的语句。

我还注意到您的所有varchar声明都缺少长度参数。这使得它们都是一个字符长,这当然不是你的意图。表名是使用 定义的sysname,这几乎与 相同NVARCHAR(128),所以我切换到了。

CREATE PROCEDURE [dbo].[swap_Collect]
  @Table  varchar,
  @UniqueColumn varchar
AS

-- Moving the variable declaration so we can use them in both the IF and the ELSE
DECLARE @Table_temp as varchar = @Table + '_temp'
       ,@SQL varchar(500)
       ,@NL varchar(2) = CONCAT(CHAR(10),CHAR(13)); 
        -- This is a new line character to make the dynamic code more readable.

BEGIN
  IF (OBJECT_ID(@Table) IS NOT NULL ) --The variable is fine here.
    BEGIN

      -- Delete from the base table here.      
      SET @SQL = CONCAT(
        'DELETE FROM ',QUOTENAME(@Table), @NL,
        'WHERE ',QUOTENAME(@UniqueColumn),
        ' IN (SELECT ',QUOTENAME(@UniqueColumn),' FROM ', QUOTENAME(@Table_temp),');');
      --PRINT @SQL;
      EXEC sp_executesql @SQL;

      -- Insert into the base table here.
      SET @SQL = CONCAT(
        'INSERT INTO ', QUOTENAME(@Table), @NL,
        'SELECT * FROM ', QUOTENAME(@Table_temp),';');
      --PRINT @SQL;
      EXEC sp_executesql @SQL;

      SELECT 1
    END
  ELSE
      BEGIN 
        -- Insert into the base table here.
        -- SELECT...INTO only works if the target table doesn't exist. Since @Table does exist
        -- we'll use INSERT INTO instead. 
        SET @SQL = CONCAT(
          'INSERT INTO ', QUOTENAME(@Table), @NL,
          'SELECT * FROM ', QUOTENAME(@Table_temp),';');
        --PRINT @SQL;
        EXEC sp_executesql @SQL;

        SELECT 1
      END
END

由于它使用它,这里有一个很好的参考。动态 SQL 的注意事项

于 2020-05-19T21:37:01.890 回答