Sql 基于CSV输入参数从#temp表中删除列
如果列表中存在列,如何从SQL Server临时表中删除列 比如: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中存在的其他列 我认为我们可以做
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等)的列
- 如果您试图删除表中的最后一列
- 如果您有一些列的名称选择得非常糟糕,而这些列却以某种方式绕过了我试图在这里包含的所有保护
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等)的列
- 如果您试图删除表中的最后一列
- 如果您有一些列的名称选择得非常糟糕,而这些列却以某种方式绕过了我试图在这里包含的所有保护