我正在尝试找出代码来生成循环通过表的内容并检查它是否仍然是有效列并删除所有无效的列。
declare @counter int
declare @col_count int
declare @col_name char(100)
declare @temp_sql char(100)
set @counter = 0
SELECT @col_count = COUNT(*) from sys.columns
where Object_ID = Object_ID(N'test')
AND name <> 'pk_test'
while @counter < @col_count
begin
with CTE as (
select name, row_number() over (order by column_id) as ColNo
from sys.columns where object_id = object_id('test') AND name <> 'pk_test'
)
select @col_name = name from CTE where ColNo = ((@counter) + 1)
SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';'
EXECUTE (@temp_sql);
set @counter = @counter + 1
end
由于某种原因EXECUTE导致代码跳过其他所有调用,但是如果我用注释取出执行并抛出一个打印,它将显示所有有效的drop语句。
我试过这样做:
SET @temp_sql = @temp_swl + 'ALTER TABLE test DROP column ' + @col_name
enter code here
我试图一次性组合所有的alter table,但它似乎不起作用。
我觉得我错过了一些小事!
答案 0 :(得分:2)
您每次都使用计数器重新生成表格 - 除非您有时使用alter table
语句删除一行(即列)。
相反,首先生成表,然后循环遍历它。所以,替换这个:
while @counter < @col_count
begin
with CTE as (
select name, row_number() over (order by column_id) as ColNo
from sys.columns where object_id = object_id('test') AND name <> 'pk_test'
)
select @col_name = name from CTE where ColNo = ((@counter) + 1)
SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';'
EXECUTE (@temp_sql);
set @counter = @counter + 1
end
有了这个:
declare @columns table (colnum int not null identity(1, 1), colname varchar(255));
insert into @columns(colname)
select name
from sys.columns
where object_id = object_id('test') AND name <> 'pk_test';
set @col_count = max(colnum) from @columns;
while @counter < @col_count
begin
select @col_name = name from @columns where ColNo = ((@counter) + 1);
SET @temp_sql = 'ALTER TABLE test DROP column ' + @col_name + ';'
EXECUTE (@temp_sql);
set @counter = @counter + 1;
end;
我不打算评论你在做什么,但这应该通过预先计算列列表来解决“跳过”问题。这样,列表不受alter table
语句的影响。
答案 1 :(得分:1)
这是一种更简单的方法,它不需要游标(这是while循环的另一个名称),并且没有跳过任何东西的可能性。请注意,我假设“无效”表示“没有名称pk_test
”。如果“无效”是指其他内容,请澄清。当然,您可能希望确保该表首先包含一个名为pk_test
的列,否则最后一个ALTER
将失败 - 您的代码当前不会检查该列。
DECLARE @t NVARCHAR(512), -- the table we're affecting
@c SYSNAME; -- the column we want to keep
SELECT @t = N'dbo.test', @c = N'pk_test';
IF EXISTS
(
SELECT 1 FROM sys.columns
WHERE [object_id] = OBJECT_ID(@t)
AND name = @c
)
BEGIN
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';
SELECT @sql = @sql + N'
ALTER TABLE ' + @t + ' DROP COLUMN ' + QUOTENAME(name) + ';'
FROM sys.columns WHERE [object_id] = OBJECT_ID(@t) AND name <> @c;
PRINT @sql;
-- EXEC sp_executesql @sql;
END
ELSE
BEGIN
PRINT 'Sorry, can't delete all columns from ' + @t + '.';
END