根据CSV输入参数从#temp表中删除列

时间:2013-11-26 19:23:55

标签: sql sql-server

如果从列表中存在列,则如何从SQL Server临时表中删除列?

类似的东西:

    DECLARE @cols AS NVARCHAR(MAX)
     @cols will have value like [first_name], [last_name], .....
     So @cols = '[first_name], [last_name], .....'

现在

    ALTER TABLE #my_tables
    DROP COLUMN @cols

如何检查#my_tables是否包含last_name?如果不是忽略它而不是抛出错误。我仍然需要删除@cols中存在的其他列

我认为如果各列上存在条件,我们可以这样做。

由于

4 个答案:

答案 0 :(得分:3)

我同意CRAFTY DBA:您应该将这些值作为表值参数传递,而不是以逗号分隔列表。但这并没有真正改变问题:您仍然要动态生成所有DROP COLUMN命令,无论是使用表值函数从CSV解析列名,还是从TVP中提取。

我将继续您目前对逗号分隔列表的要求。

首先,创建一个字符串拆分功能。这是我使用的那个:

CREATE FUNCTION [dbo].[SplitString]
    (
        @List NVARCHAR(MAX),
        @Delim VARCHAR(255)
    )
    RETURNS TABLE
    AS
        RETURN ( SELECT [Value] FROM 
          ( 
            SELECT 
              [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
              CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
            FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
              FROM sys.all_objects) AS x
              WHERE Number <= LEN(@List)
              AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
          ) AS y
        );
GO

现在,创建一个愚蠢的#temp表:

CREATE TABLE #foo(id INT, x INT);

现在,您可以声明要尝试删除的列的列表,创建一个动态SQL语句,在删除它们之前检查它们是否存在,然后删除它们可以执行的操作:

DECLARE @cols VARCHAR(MAX);
SET @cols = '[first_name], [last_name], [id]';

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'IF EXISTS (SELECT 1 FROM tempdb.sys.columns AS c 
   WHERE [object_id] = OBJECT_ID(''tempdb..#foo'') 
   AND name = ' + REPLACE(REPLACE(QUOTENAME(s.Value, ''''),']',''),'[','') + ')
  ALTER TABLE #foo DROP COLUMN ' + s.Value + ';' 
FROM dbo.SplitString(@cols, ',') AS s;

EXEC sp_executesql @sql;

SELECT * FROM #foo; -- this only returns the column x

如果再次运行这部分代码,对同一个表运行,它将无误地运行。您可能遇到的一些错误是:

  • 如果您尝试删除参与任何约束的列(默认值,PK,FK,检查等)。
  • 如果您尝试删除表格中的最后一列。
  • 如果您的列名称选择真的很差,那么我会尝试在此处包含所有保护措施。

答案 1 :(得分:1)

您可以使用动态SQL;但请注意SQL注入。

我会将@cols作为参数传递给存储过程。

程序正文如下。

-- Declare local variables
DECLARE @STMT NVARCHAR(MAX);

-- Create the stmt
SET @STMT = 'ALTER TABLE #my_tables DROP COLUMN ' + @cols;

-- Execute the stmt
EXEC sp_executesql @STMT;

我宁愿传递一个表值参数,但这只是我。

答案 2 :(得分:1)

检查你需要记住的临时表的列,它存储在temp db

select *
from tempdb.sys.columns
where object_id = object_id('tempdb..#my_tables')

答案 3 :(得分:0)

使用此:

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'

它将返回列是否存在,使用此SQL的响应来决定是否执行删除