SQL Server sp_msforeachtable用法只select那些满足某些条件的表
我正在试图写这个查询来查找具有特定值的特定列的所有表。 这是我迄今为止所做的 –
EXEC sp_MSforeachtable @command1=' IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE") BEGIN IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0 BEGIN SELECT * FROM ? WHERE EMP_CODE="HO081" END END '
我希望我的内涵很清楚,我只想selectEMP_CODE
列所在的那些表,在这些表中我想select那些EMP_CODE='HO081'
。
编辑 –
现在它是这样的。 但是我不能在查询中replace@EMPCODE
variables。
DECLARE @EMPCODE AS VARCHAR(20) SET @EMPCODE='HO081' EXEC sp_MSforeachtable @command1=' DECLARE @COUNT AS INT SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+''' IF @COUNT>0 BEGIN PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+''''''' END ',@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME='''+@EMPCODE+''')'
你知道sp_MSforeachtable
是如何没有logging的,并可能在任何时候离开/被修改?
那么,如果你很高兴忽略它,它有另一个名为@whereand
参数,它被附加到正在用来查找表的内部查询的WHERE
子句(并且应该以AND
开头)。
你还必须知道有一个别名, o
对sysobjects
,和第二syso
名syso
对sys.all_objects
。
使用这些知识,你可以制作你的@whereand
参数:
EXEC sp_MSforeachtable @command1='...', @whereand='AND o.id in (select object_id from sys.columns c where c.name=''EMP_CODE'')'
您现在也可以简化您的command1
,因为您知道它只能在包含EMP_CODE
列的表上运行。 我可能会拿出COUNT(*)
条件,因为我没有看到它增加了什么价值。
根据您的进一步工作进行更新,并针对一张表进行testing:
DECLARE @EMPCODE AS VARCHAR(20) SET @EMPCODE='HO081' declare @sql nvarchar(2000) set @sql = ' DECLARE @COUNT AS INT SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+''' IF @COUNT>0 BEGIN PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+''''''' END ' EXEC sp_MSforeachtable @command1=@sql,@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME=''EMP_CODE'')'
(我已经恢复@whereand
和查询EMP_CODE
,因为你不想在那里取代值)。
问题是,你可以将参数传递给存储过程或文字 ,但不能在它们之间执行计算/组合操作 – 所以我将sql语句的构造移到了单独的操作中。
我想你会得到某种错误,也许Invalid column name 'EMP_CODE'
?
这是因为代码是在检查列之前编译的。 你可以这样做,而不是。
EXEC sp_MSforeachtable @command1=' IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE") BEGIN EXEC('' IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0 BEGIN SELECT * FROM ? WHERE EMP_CODE="HO081" END '') END '