19

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

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

2 回答 2

51

你知道如何sp_MSforeachtable是无证的,并且可能随时消失/被修改吗?

好吧,如果您愿意忽略它,它还有另一个名为 的参数@whereand,它附加到WHERE用于查找表的内部查询的子句中(并且应该以 开头AND)。

您还必须知道有一个别名o反对,以及反对sysobjects的第二个别名。sysosys.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查询还原为EMP_CODE,因为您不想替换那里的值)。

问题是,您可以将参数传递给存储过程或literals,但不能在它们之间执行计算/组合操作 - 所以我将 sql 语句的构造移到单独的操作中。

于 2012-03-13T07:57:35.293 回答
9

我猜你可能会遇到某种错误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
'
于 2012-03-13T08:06:22.840 回答