Sql 具有可变列名的动态update语句
我们希望在几个SQL Server数据库中进行更新,将某个表中的所有空值更改为空字符串,而不是空字符串。我们可能会在数百个数据库中执行此操作。表名将始终相同,但列名是可变的,取决于前端应用程序的配置方式(不要判断…我没有创建此系统)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
有没有一种方法可以在不提前知道列名的情况下对所有这些列进行更新?您可以查看
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