Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 基于CSV输入参数从#temp表中删除列_Sql_Sql Server - Fatal编程技术网

Sql 基于CSV输入参数从#temp表中删除列

Sql 基于CSV输入参数从#temp表中删除列,sql,sql-server,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], .....' 现在 如何检查my_表是否包含姓氏?如果没有,则忽略它,而不是抛出错误。我仍然需要删除@cols中存在的其他列 我认为我们可以做

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

比如:

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

如何检查my_表是否包含姓氏?如果没有,则忽略它,而不是抛出错误。我仍然需要删除@cols中存在的其他列

我认为我们可以做,如果存在条件对个别列

谢谢你使用这个:

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'
它将返回该列是否存在,使用此SQL的响应来决定是否执行删除操作

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

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

您可以使用动态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;

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

您可以使用动态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;

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

要检查临时表的列,您需要记住它是否存储在临时数据库中

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

要检查临时表的列,您需要记住它是否存储在临时数据库中

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

我同意狡猾的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
现在,您可以声明要尝试删除的列的列表,创建一个动态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、check等)的列
  • 如果您试图删除表中的最后一列
  • 如果您有一些列的名称选择得非常糟糕,而这些列却以某种方式绕过了我试图在这里包含的所有保护

我同意狡猾的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
现在,您可以声明要尝试删除的列的列表,创建一个动态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、check等)的列
  • 如果您试图删除表中的最后一列
  • 如果您有一些列的名称选择得非常糟糕,而这些列却以某种方式绕过了我试图在这里包含的所有保护

我已经在使用一个动态查询,但是当@cols在列表中包含like[Address]时,它会抛出错误。ALTER table DROP COLUMN失败,因为列“Address”在表“my”中不存在_tables@AaronBertrand,my temp table#my_tables不包含该地址列,但我的“@cols”包含的地址是一个单独的字段。我知道,我的问题不清楚。你现在能读懂我的问题吗?我已经更新了它。ThanksI刚刚发布了一个关于如何获取列列表并将其从表中删除的快速示例。同样,我会使用一个表变量参数@TVP。对于表中的每个列名,创建动态SQL以检查表中是否存在该列,如果确实存在,则删除该列。Gavin的代码特定于“临时表”,这是您的需求。只是把这些部分放在一起…我已经在使用一个动态查询,但是当@cols在列表中包含like[Address]时,它会抛出错误。ALTER table DROP COLUMN失败,因为表#my中不存在列“Address”_tables@AaronBertrand,我的临时表#我的#表不包含该地址列,但我的“@cols”将该地址作为分隔字段之一。我知道,我的问题不清楚。你现在能读懂我的问题吗?我已经更新了它。ThanksI刚刚发布了一个关于如何获取列列表并将其从表中删除的快速示例。同样,我会使用一个表变量参数@TVP。对于表中的每个列名,创建动态SQL以检查表中是否存在该列,如果确实存在,则删除该列。Gavin的代码特定于“临时表”,这是您的需求。把这些部分放在一起…你为什么要费心从临时表中删除列?忽略它们。因为我需要从另一个动态透视值中附加相同的列和值,所以为什么不等到知道所有列都是什么,再构建#temp表呢?或者只将新列命名为first_name2、last_name2等。?或者一开始就避免使用临时表?您知道,您需要花很长时间来整合作用域,尝试构建和更改临时表,同时还需要使用动态SQL…为什么