17

Sto cercando di scrivere questa query per trovare tutte le tabelle con colonna specifica con qualche valore specifico. Questo è quello che ho fatto finora -SQL Server sp_msforeachtable utilizzo per selezionare solo quelle tabelle che soddisfano alcune condizioni

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 
' 

Spero che le mie intenzioni sono chiare, voglio solo di scegliere solo i tavoli dove è presente e in quelle tabelle colonna EMP_CODE voglio selezionare le righe in cui EMP_CODE='HO081' .

Edit -

Ora si erge come questo. Ma non sono in grado di sostituire la variabile @EMPCODE nella query.

DECLARE @EMPCODE AS VARCHAR(20) 
SET @EMPCODE='HO081' 
EXEC sp_MSforeachtable 
@command1=' 
    DECLARE @COUNT AS INT 
    SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''[email protected]+''' 
    IF @COUNT>0 
    BEGIN 
     PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' 
     --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''[email protected]+''''''' 
    END 
',@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME='''[email protected]+''')' 

risposta

45

Sapete come sp_MSforeachtable è documentato, e può andare via in qualsiasi momento/essere modificato?

Beh, se sei felice di ignorare che, ha un altro parametro chiamato @whereand, che viene aggiunto alla clausola di WHERE della query interna che viene utilizzato per trovare i tavoli (e dovrebbe iniziare con un AND).

Dovete anche sapere che c'è un alias, o contro sysobjects, e un secondo alias syso contro sys.all_objects.

Usando questa conoscenza, si potrebbe mestiere tua parametro @whereand come:

EXEC sp_MSforeachtable 
@command1='...', 
@whereand='AND o.id in (select object_id from sys.columns c where c.name=''EMP_CODE'')' 

È ora possibile semplificare anche la vostra command1, poiché si sa che verrà eseguito solo contro le tabelle contenenti una colonna EMP_CODE. Probabilmente prenderei anche la condizione COUNT(*), dal momento che non vedo quale valore stia aggiungendo.


aggiornamento, sulla base di ulteriori lavori, e testato contro una tabella:

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='''[email protected]+''' 
    IF @COUNT>0 
    BEGIN 
     PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)'' 
     --PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''[email protected]+''''''' 
    END 
' 
EXEC sp_MSforeachtable 
@[email protected],@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME=''EMP_CODE'')' 

(ho ritornato il @whereand per interrogare per EMP_CODE, dal momento che non si vuole sostituire il valore lì).

Il problema è che, è possibile passare parametri a una stored procedure, o letterali, ma non è possibile eseguire calcoli/combinando azioni tra loro - così ho spostato la costruzione dell'istruzione SQL fuori in un azione separata.

+4

+1 per voi mostrare cosa si può fare, ma implicitamente che ti dice di non farlo;?) – cairnz

+0

@Damien_The_Unbeliever Supponiamo se scrivo 'IF (SELECT COUNT (*) FROM WHERE EMP_CODE = '' '+ @EMPCODE + '' ')> 0', allora perché mi sta dando una sintassi errata vicino a '+'. Sto cercando di passare il valore 'EMP_CODE' attraverso una variabile. –

+0

@SohamDasgupta - È un po 'complicato diagnosticare questo tipo di problema nella sezione dei commenti, dal momento che avrei davvero bisogno di vedere l'intera query così come è ora, e questo non funzionerà nei commenti. Vorrei ancora interrogare quel particolare pezzo di codice però - perché * contare * il numero di righe corrispondenti invece di selezionarle semplicemente? I set di risultati vuoti sono solitamente abbastanza facili da gestire. –

9

Immagino tu abbia un errore di qualche tipo, forse Invalid column name 'EMP_CODE'?

È perché il codice viene compilato prima di controllare la colonna. Si potrebbe fare come questo, invece.

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

Funziona alla grande. Grazie. –

Problemi correlati