web-dev-qa-db-ja.com

SQL Serverの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+''')'
17
Soham Dasgupta

_sp_MSforeachtable_が文書化されておらず、いつでも消える/修正される可能性があることを知っていますか?

それを無視してよければ、テーブルを見つけるために使用されている内部クエリのWHERE句に追加される_@whereand_という別のパラメータがあります(開始する必要があります) AND)。

また、oに対するsysobjectsエイリアスと、_sys.all_objects_に対する2番目のエイリアスsysoがあることも知っておく必要があります。

この知識を使用して、_@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(*)条件も削除します。


今後の作業に基づいて更新し、1つのテーブルに対してテストしました。

_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_を照会しました。そこで値を置き換えたくないので)。

問題は、parametersをストアドプロシージャに渡すことができる、またはliteralsを渡すことができるが、それらの間で計算/アクションの組み合わせを実行できないことです。 SQLステートメントを別のアクションに出力します。

47

おそらく_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
'
9
Mikael Eriksson