SQL Server sp_msforeachtable用法仅选择满足某些条件的表

时间:2012-03-13 07:34:54

标签: sql-server sql-server-2008 stored-procedures sql-server-2005 sp-msforeachtable

我正在尝试编写此查询以查找具有特定列且具有某些特定值的所有表。这就是我到目前为止所做的 -

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
'

我希望我的意图很明确,我只想选择那些列EMP_CODE所在的表,而在那些表中我想选择那些EMP_CODE='HO081'的行。

修改

现在它就像这样。但我无法在查询中替换@EMPCODE变量。

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+''')'

1 个答案:

答案 0 :(得分:47)

你知道sp_MSforeachtable如何没有记录,并且可能随时被删除/被修改?

好吧,如果你很乐意忽略它,它有另一个名为@whereand的参数,它被附加到用于查找表的内部查询的WHERE子句中(和应该以{{1​​}}开头。

您还必须知道有一个别名AND针对o,另一个别名sysobjects针对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(*)

(我已将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,因为您不想替换那里的值。

问题在于,您可以将参数传递给存储过程或文字,但是您无法在它们之间执行计算/组合操作 - 所以我搬了将sql语句构造成一个单独的动作。