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@EMPCODEvariables。

 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开头)。

你还必须知道有一个别名, osysobjects ,和第二sysosysosys.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 '