Eseguire comando diverso rispetto a una variabile

di kkzan il
17 risposte
Buongiorno a tutti, avrei questa necessità:
su questa query (semplificata):

declare @x as varchar
set @x=2

select *
from <tabella>
where
......

avrei bisogno di eseguire il where con la condizione <campo> like '%' se @x=0 oppure <campo> in @x se il valore è diverso da 0.
Esiste un modo per farlo?

Grazie

17 Risposte

  • kkzan ha scritto:


    avrei bisogno di eseguire il where con la condizione <campo> like '%' se @x=0 oppure <campo> in @x se il valore è diverso da 0.
    Se non riesci a integrare direttamente la condizione nella WHERE usando gli operatori logici AND e OR con le relative parentesi, puoi ricorrere all'uso di un IF (vedi qualche esempio).

    Ciao!
  • Ok l'if, ma il mio problema è creare la condizione in un caso usando 'like' e nel secondo caso usando 'in'; provo a spiegarmi meglio:
    dovrebbe essere con questa logica

    if @x=0
    where <campo> like '%'
    else
    where <campo> in @x
    end

    ma una istruzione scritta così non può funzionare
  • Mi viene in mente qualcosa del tipo
    
    if @x=0
      select * from tabella where <campo> like '%'
    else
      select * from tabella where <campo> in @x
    
  • Ah ok, giusto!
    non so perché pensavo di cambiare solo la condizione.....
    grazie 1000
  • Io valuterei anche
    
    SELECT *
    FROM Tabella
    WHERE (@x=0 AND <campo> LIKE '%')
       OR (@x!=0 AND <campo> IN @x)
    Così il blocco della SELECT...FROM viene scritto una volta sola...
    Onestamente non saprei quale possa essere la soluzione più efficiente, ma un paio di piani di esecuzione e il gioco è fatto...
  • Grazie proverò anche questo!
  • Confermo che l'ultimo esempio è quello che uso anche io in questi casi.
  • Salve a Tutti,

    tendenzialmente quanto riportato da @Sgrubak dovrebbe generare i piani migliori, ANCHE SE, purtroppo, il caching del piano di esecuzione puo' fortemente penalizzare le situazioni nel branch di codice "alternativo" ... quindi se la prima esecuzione di
    @x = 0 quindi
    if @x=0
    select * from tabella where <campo> like '%'

    else
    select * from tabella where <campo> in @x

    genera un piano di esecuzione ottimale per where <campo> like '%',
    la seconda esecuzione con @x <> 0 potrebbe incorrere in forti penalizzazioni visto che verra' eseguito tutt'altro filtro...
    quindi, in caso di utilizzo di questa modalita' consiglierei l'impostazione di WITH RECOMPILE nel caso di stored procedure, che vanifica ovviamente molte ottimizzazioni MA sicuramente non fa incorrere in problematiche di piani di esecuzione non corretti ...

    salutoni romagnoli

    Andrea
  • asql ha scritto:


    Salve a Tutti,

    tendenzialmente quanto riportato da @Sgrubak dovrebbe generare i piani migliori, ANCHE SE, purtroppo, il caching del piano di esecuzione puo' fortemente penalizzare le situazioni nel branch di codice "alternativo" ... quindi se la prima esecuzione di
    @x = 0 quindi
    if @x=0
    select * from tabella where <campo> like '%'

    else
    select * from tabella where <campo> in @x

    genera un piano di esecuzione ottimale per where <campo> like '%',
    la seconda esecuzione con @x <> 0 potrebbe incorrere in forti penalizzazioni visto che verra' eseguito tutt'altro filtro...
    quindi, in caso di utilizzo di questa modalita' consiglierei l'impostazione di WITH RECOMPILE nel caso di stored procedure, che vanifica ovviamente molte ottimizzazioni MA sicuramente non fa incorrere in problematiche di piani di esecuzione non corretti ...

    salutoni romagnoli

    Andrea
    ciao Andrea,

    e se si facesse così chiamando altre due stored a seconda del valore di @x ?
    
    if @x=0
         exec  dbo.spExecSelectWhereLike ....
    else
        exec  dbo.spExecSelectWhereLikeIn ...
    
  • Così triplichi il numero di stored procedure necessarie.
  • Sinceramente starei sulla prima risposta che ti hanno dato, ovvero:
    
    SELECT *
    FROM Tabella
    WHERE (@x=0 AND <campo> LIKE '%')
       OR (@x!=0 AND <campo> IN @x)
    
    Se poi incappi nel problema di performance che hanno segnalato (e ci può stare), puoi aggiungere l'opzione "RECOMPILE" in modo da far studiare al DB un nuovo piano di esecuzione.

    In questo caso paghi sempre lo scotto dello studio del piano di esecuzione migliore, però eviti di incappare nel problema segnalato
  • Toki ha scritto:


    Così triplichi il numero di stored procedure necessarie.
    vero .... ma in fondo mica devi portarle sulle spalle le stored

    Personalmente in caso di stored molto usata e pesante con l'altro metodo un pensierino ce lo farei
  • Salve,

    PiGi78 ha scritto:


    Sinceramente starei sulla prima risposta che ti hanno dato, ovvero:
    
    SELECT *
    FROM Tabella
    WHERE (@x=0 AND <campo> LIKE '%')
       OR (@x!=0 AND <campo> IN @x)
    
    Se poi incappi nel problema di performance che hanno segnalato (e ci può stare), puoi aggiungere l'opzione "RECOMPILE" in modo da far studiare al DB un nuovo piano di esecuzione.

    In questo caso paghi sempre lo scotto dello studio del piano di esecuzione migliore, però eviti di incappare nel problema segnalato
    qui il problema del RECOMPILE "non serve e non aiuta"... il solo fatto dell'OR implica piani NON ottimali in se', al di la' del sicuro utilizzo di SQL Server della short circuit evaluation...
    il RECOMPILE puo' "aiutare" nel caso
    IF @x > 0
    SELECT a
    ELSE
    SELECT b

    dove i il branch di codice eseguito varia completamente per il batch in corso... nel caso di sopra, invece l'OR non richiede un RECOMPILE in quanto comunque il piano generato NON sara' ottimale...

    il "modo piu'" valido, in questo senso, e' "esterno" al chiamante...
    cioe' che il client esterno, in base al valore "esterno" di @x, chiami la stored procedure A oppure B... ma questo sposta molto il lavoro di logica lato client...
    quindi il secondo modo ottimale e' il branching interno alla stored procedure primaria come indicato da @sspintux,
    if @x=0
    exec dbo.spExecSelectWhereLike ....
    else
    exec dbo.spExecSelectWhereLikeIn ...

    MA, e c'e' sempre un ma , c'e' il maggior "costo" di manutenzione di 3 stored procedures, come giustamente indica @Toki

    nella pratica, se non fortemente penalizzante, e' uso comune il
    WHERE (@x=0 AND <campo> LIKE '%')
    OR (@x!=0 AND <campo> IN @x)

    ma un giro di test (e non con il db di sviluppo) ce lo farei

    ad ogni modo "ho visto cose che...", dove queste sottigliezze sono da considerarsi molto marginali

    salutoni romagnoli
    --
    Andrea
  • sspintux ha scritto:


    Toki ha scritto:


    Così triplichi il numero di stored procedure necessarie.
    vero .... ma in fondo mica devi portarle sulle spalle le stored
    Prova a mettere mano a database con 300 stored procedure non documentate , poi capirai meglio la necessità di non far proliferare "cose" se non strettamente necessario.
    Creare 3 stored procedure per gestire una where condition possiamo farlo rientrare nel magico mondo degli antipatterns.

    Questione performance: c'è davvero una questione di performance su questa ricerca? quanti records ci sono in questa tabella?
Devi accedere o registrarti per scrivere nel forum
17 risposte