20

我们希望在几个 SQL Server 数据库中进行更新,以将某个表中的所有 NULL 值更改为空字符串而不是 NULL。我们可能会在数百个数据库中执行此操作。表名将始终相同,但列名根据前端应用程序的配置方式是可变的(不要判断...我没有创建这个系统)。

有没有办法在不提前知道列名的情况下对所有这些列进行更新?

4

7 回答 7

23

您可以在动态 sql 中传递列的名称:

declare @sql nvarchar (1000);
set @sql = N'update table set ' + @column_name + '= ''''';

exec sp_executesql @sql;
于 2012-10-11T19:30:33.863 回答
3

您可以查看sys.columns表并加入表名或 object_id。

 DECLARE @OBJ_ID INT

 SELECT @OBJ_ID = OBJECT_ID
 FROM SYS.tables
 WHERE name = 'YOURTABLE'

 SELECT * FROM SYS.columns
 WHERE OBJECT_ID = @OBJ_ID

您可以使用namesys.columns 查询中的字段作为执行更新的基础。

于 2012-10-11T19:07:27.457 回答
2

假设您只需要 varchar/char 类型的所有列(或将类型过滤器更改为您需要的任何内容):

DECLARE @tableName varchar(10)
SET @tableName = 'yourtablenamehere'

DECLARE @sql VARCHAR(MAX)
SET @sql = ''

SELECT @sql = @sql + 'UPDATE ' + @tableName + ' SET ' + c.name + ' = '''' WHERE ' + c.name + ' IS NULL ;'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE t.name = @tableName AND y.name IN ('varchar', 'nvarchar', 'char', 'nchar')

EXEC (@sql)
于 2012-10-11T20:07:10.320 回答
1

这可以通过游标来实现。您首先选择@Darren 提到的列名,然后使用这些值设置光标并循环:

Open oColumnsCursor
Fetch Next From oColumnscursor
    Into @ColumnName

While @@FETCH_STATUS=0
    Begin
        Set @oQuery = 'Update [DB]..[Table] Set [' + @ColumnName + '] = ''NewValue'' Where [' + @ColumnName + '] = ''OldValue'''
        Execute(@oQuery)
        Fetch Next From oColumnscursor Into @ColumnName
        Set @oCount = @oCount + 1
    End

Close oColumnsCursor;
Deallocate oColumnsCursor;
于 2019-02-04T22:23:55.113 回答
1

当您知道表名时,这将起作用:

DECLARE @tableName varchar(10)
SET @tableName = 'Customers'

DECLARE @sql VARCHAR(MAX)
SET @sql = ''

SELECT @sql = @sql + 'UPDATE ' + @tableName + ' SET ' + c.name + ' = ISNULL('+ c.name +','''');'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE y.name IN ('varchar', 'nvarchar', 'char', 'nchar')
AND t.name = @tableName;

EXEC(@sql);

这将迭代数据库中的所有表和所有列:

DECLARE @sql VARCHAR(MAX)
SET @sql = ''

SELECT @sql = @sql + 'UPDATE ' + t.name + ' SET ' + c.name + ' = ISNULL('+ c.name +','''');'
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.types y ON c.system_type_id = y.system_type_id
WHERE y.name IN ('varchar', 'nvarchar', 'char', 'nchar');

EXEC(@sql); 
于 2020-01-10T00:30:53.477 回答
1

下面是程序。

ALTER PROCEDURE [dbo].[util_db_updateRow]
    @colval_name  NVARCHAR (30), -- column and values e.g. tax='5.50'
    @idf_name  NVARCHAR (300),   -- column name
    @idn_name  NVARCHAR (300),   -- column value
    @tbl_name  NVARCHAR (100)    -- table name
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX)

    -- construct SQL
    SET @sql = 'UPDATE ' + @tbl_name + '  SET ' + @colval_name + 
               ' WHERE ' + @idf_name + '=' + @idn_name;

    -- execute the SQL
    EXEC sp_executesql @sql
    SET NOCOUNT OFF  

    RETURN
END
于 2020-09-02T13:02:46.523 回答
0

下面是存储过程,您可以在其中传递模式名称、表名称和以逗号分隔的列名列表。它仅适用于 Sql Server 2016 或更高版本。

CREATE OR ALTER PROCEDURE UpdateData
(@SchemaName NVARCHAR(Max),@TableName NVARCHAR(MAX),@ColumnNames NVARCHAR(MAX))
AS
BEGIN
DECLARE @DynamicSql NVARCHAR(MAX);
SET @DynamicSql =  'UPDATE ' +'[' +@SchemaName+'].' + '[' +@TableName+']' +' SET ' + STUFF((SELECT ', [' + C.name + '] = ' + '''NEW_VALUE''' 
FROM sys.columns C
INNER JOIN sys.tables T ON T.object_id = C.object_id
INNER JOIN sys.schemas S ON T.schema_id = S.schema_id
WHERE 
    T.name = @TableName
    AND S.Name = @SchemaName
    AND [C].[name] in (SELECT VALUE FROM string_split(@ColumnNames,','))
FOR XML PATH('')), 1,1, '')
print @DynamicSql;
EXEC (@DynamicSql);
END
于 2021-09-08T05:50:16.023 回答