我有一张超过130列的表格(不要问 - 我没有成功)。我们需要从此表中删除每个空行(每个字段为空),而不显式列出每列。理想情况下,我想要一个使用动态SQL的解决方案,并且可以应用于任何表。我怎么能这样做?
答案 0 :(得分:3)
这至少可以帮助你:
DECLARE @myTable VARCHAR(MAX)
SET @MyTable = 'myTable'
DECLARE @SQL VARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ' AND ','')+ '(' +quotename(COLUMN_NAME) + ' = '''' OR ' +quotename(COLUMN_NAME) + ' IS NULL)'
FROM information_schema.columns
WHERE table_NAME = @myTable
SET @SQL = 'DELETE FROM ' + quotename(@myTable) + ' WHERE ' + @sql
select @sql
请注意使用QUOTENAME
来处理奇怪命名的列。另请注意,这假设所有列都是字符串列(或者可以隐式转换为字符串)。在您的解决方案中,您可能需要一些条件逻辑(使用CASE)来处理不同的数据类型,例如。
SELECT @SQL = COALESCE(@SQL + ' AND ','')+ '(' +quotename(COLUMN_NAME) + ' = ' + CASE WHEN data_type = 'int' then '0' when data_type = 'varchar' then '''' else '''' end + ' OR ' +quotename(COLUMN_NAME) + ' IS NULL)'
FROM information_schema.columns
WHERE table_NAME = @myTable
答案 1 :(得分:2)
这将删除每列null
的行。
-- Sample table
declare @T table
(
Col1 int,
Col2 datetime,
Col3 bit,
Col4 nvarchar(max)
)
-- Add sample data
insert into @T values
(null, null, null, null),
( 1, null, null, null),
(null, getdate(), null, null),
(null, null, 1, null),
(null, null, null, '')
-- Delete rows where all column values are null
;with C(XmlCol) as
(
select
(select T.*
for xml path('row'), type)
from @T as T
)
delete from C
where C.XmlCol.exist('row/*') = 0
结果:
Col1 Col2 Col3 Col4
----------- ----------------------- ----- ----------
1 NULL NULL NULL
NULL 2011-11-23 14:09:42.770 NULL NULL
NULL NULL 1 NULL
NULL NULL NULL
http://data.stackexchange.com/stackoverflow/q/118893/
修改强>
如果您要删除空字符串字段以及null
,它将如下所示:
;with C(XmlCol) as
(
select
(select T.*
for xml path('row'), type)
from @T as T
)
delete from C
where C.XmlCol.exist('row/*[. != ""]') = 0
答案 2 :(得分:0)
我会考虑查看包含有关表,列,键等信息的INFORMATION_SCHEMA
视图。使用TABLES
和COLUMNS
视图可以让您获得非常强大的解决方案。这是MSDN documentation。
答案 3 :(得分:0)
DECLARE @SQL VARCHAR(MAX)
SELECT @SQL = COALESCE(@SQL + ' AND ','') +
(CASE
WHEN UPPER(DATA_TYPE) = 'INT' THEN ('(' +quotename(COLUMN_NAME) + ' = 0 OR ' +quotename(COLUMN_NAME) + ' IS NULL)')
WHEN UPPER(DATA_TYPE) = 'VARCHAR' THEN ('(' +quotename(COLUMN_NAME) + ' = '''' OR ' +quotename(COLUMN_NAME) + ' IS NULL)')
-- More conditions are goes here
-- Cover all data type (DATA_TYPE) used at your target table, or you may cover all existing data types
ELSE ''
END)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_NAME = @targetTable
SET @SQL = 'DELETE FROM ' + QUOTENAME(@targetTable) + ' WHERE ' + @sql
SELECT @SQL
答案 4 :(得分:0)
对于像这样的事情,我倾向于使用视觉查询构建器或设计器。它们会自动输入所有字段名称,您可以将IS NULL或=''复制并粘贴到每个字段的条件编辑中,并生成正确的查询。在构建并测试它们作为SELECT后,我将它们转换为DELETE或任何其他需要的查询类型。
答案 5 :(得分:0)
@Elias Hossain的参数化模式的答案复制如下。
create proc dbo.spDeleteRowsWhereAllColsAreNull
@Schema nvarchar( 116 ),
@Table nvarchar( 116 )
as
begin
declare
@RetMsg nvarchar( max ),
@CountRows int,
@ProcName nvarchar( 255 ) = N'dbo.spDeleteRowsWhereAllColsAreNull',
@DynamicSql nvarchar( max ) = N'',
@Schema_Table nvarchar( 255 ) = @Schema + N'.' + @Table,
@Column nvarchar( 116 ),
@Lb nchar( 1 ) = char( 13 ),
@Tab nchar( 1 ) = char( 9 )
-- Check if target exists, else escape proc
if exists( select *
from sys.tables
where [object_id] = object_id( @Schema_Table ) )
begin
select @DynamicSql = 'delete from ' + @Schema_Table + N' where ' ;
-- Get all columns for target table into @DynamicSql
select @DynamicSql +=
@Tab + name+ N' is null and ' + @Lb
from sys.columns
where [object_id] = object_id( @Schema_Table ) ;
set @DynamicSql = left( @DynamicSql, len( @DynamicSql ) - 6 ) ;
-- print @DynamicSql ;
exec sp_executesql @DynamicSql ;
set @CountRows = @@rowcount ;
set @RetMsg = @ProcName + N' executed in current Database ' + db_name() + N' on table ' + @Schema_Table + N'. ' + convert( nvarchar, @CountRows ) + N' row(s) deleted.' ;
-- Print results & return success
print @RetMsg ;
return 0 ;
end
else
begin
-- Raiserror & return failure
set @RetMsg = @Schema_Table + N' does not exist current Database ' + db_name() + N'. Execution FAILED!';
raiserror( @RetMsg, 11, -1 ) ;
return -1 ;
end ;
end ;
go