Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.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 具有可变列名的动态update语句_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 具有可变列名的动态update语句

Sql 具有可变列名的动态update语句,sql,sql-server,tsql,Sql,Sql Server,Tsql,我们希望在几个SQL Server数据库中进行更新,将某个表中的所有空值更改为空字符串,而不是空字符串。我们可能会在数百个数据库中执行此操作。表名将始终相同,但列名是可变的,取决于前端应用程序的配置方式(不要判断…我没有创建此系统) 有没有一种方法可以在不提前知道列名的情况下对所有这些列进行更新?您可以查看sys.columns表,并在表名或对象id上进行联接 DECLARE @OBJ_ID INT SELECT @OBJ_ID = OBJECT_ID FROM SYS.tables

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


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

您可以查看
sys.columns
表,并在表名或对象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

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

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

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

exec sp_executesql @sql;

假设您只需要varchar/char类型的所有列(或者将类型筛选器更改为您需要的任何类型):


这可以通过游标实现。首先选择所提到的@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;

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

DECLARE@tableName varchar(10)
SET@tableName='Customers'
声明@sql VARCHAR(最大值)
设置@sql=''
选择@sql=@sql+'UPDATE'+@tableName+'SET'+c.name+'=ISNULL('+c.name+','');'
来自sys.c列
c.object\u id=t.object\u id上的内部联接sys.t表
c.system\u type\u id=y.system\u type\u id上的内部联接sys.types y
其中y.name('varchar','nvarchar','char','nchar')
和t.name=@tableName;
EXEC(@sql);
这将迭代数据库中的所有表和列:

DECLARE@sql VARCHAR(最大值)
设置@sql=''
选择@sql=@sql+'UPDATE'+t.name+'SET'+c.name+'=ISNULL('+c.name+','');'
来自sys.c列
c.object\u id=t.object\u id上的内部联接sys.t表
c.system\u type\u id=y.system\u type\u id上的内部联接sys.types y
其中y.name位于('varchar','nvarchar','char','nchar');
EXEC(@sql);

以下是程序

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

请绕开动态对象名称。@GSerg+1用于提及
quotename()
。我会说,它在这里的使用似乎有点多余,因为这只是一些内部DML。如果这是一个使用来自公共(或地狱,甚至内部)站点的用户输入执行的存储过程,我会全力以赴。
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