2014-07-26 7 views
5

Nella mia applicazione web PHP sto cercando di perfezionare la logica che, un valore definito dall'utente, assembla una query Transact-SQL che filtra su quel valore. La query viene quindi eseguita utilizzando il driver ODBC. La complicazione è che il filtraggio verrà eseguito solo sui campi derivati. Funziona perfettamente, tranne quando il campo derivato è un campo creato usando un'espressione CASE.CASE in MSSQL clausola WHERE - odbc error

Così, per esempio, ho un campo derivato come il seguente:

CASE WHEN [text_result] IS NOT NULL THEN [text_result] ELSE 
    CASE WHEN [last_event] = 1 THEN 'processed' ELSE 'unprocessed' END 
END 

Se provo e filtrare questo utilizzando il valore "non processato", quindi la query finale assemblato è ovviamente qualcosa di simile a quanto segue :

SELECT * FROM table WHERE 
    CASE WHEN [text_result] IS NOT NULL THEN [text_result] ELSE 
     CASE WHEN [last_event] = 1 THEN 'processed' ELSE 'unprocessed' END 
    END = 'unprocessed' 

Tuttavia quando questo viene eseguito ricevo il seguente errore:

Warning: odbc_execute(): SQL error: [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near the keyword 'from'., SQL state 37000 in SQLDescribeParameter in 

Ho provato a eseguire SQL Profiler e ho scoperto che sembra che l'errore sia stato generato durante la preparazione iniziale dell'istruzione e che gli app di SQL di preparazione istruzioni stiano troncando l'espressione dal nome del campo. Così appare:

SET FMTONLY ON select CASE WHEN [text_result] from table where 1=2 SET FMTONLY OFF go 

Questo è confermato quando eseguo l'istruzione SQL generata tramite MSSQL management studio e funziona perfettamente!

Spero che tutto abbia un senso. Se qualcuno ha qualche consiglio se questo problema è risolvibile o se è solo un bug nel driver sarebbe fantastico!

Questo è il PHP che sto usando per eseguire la query assemblata (estratto da una classe):

$link = odbc_connect($strConnectionString,$username,$password); 
$rResult = odbc_prepare($link,$qry); 
$success = odbc_execute($rResult,$parameters); 

var_dump ($ qry, $ parametri):

string 'SELECT * FROM table WHERE 
     CASE WHEN [text_result] IS NOT NULL THEN [text_result] ELSE 
      CASE WHEN [last_event] = 1 THEN 'processed' ELSE 'unprocessed' END 
     END = ?' 
array (size=1) 
    0 => string 'unprocessed' 
+0

mostrare il vostro blahblah php. – Mihai

+0

Certo, php aggiunto. – Raiden616

+0

Esegui 'var_dump ($ qry, $ parameters)' prima del codice che hai condiviso. –

risposta

4

primo luogo, non ho bisogno di istruzioni nidificate case. Si può solo fare:

CASE WHEN [text_result] IS NOT NULL THEN [text_result] 
    WHEN [last_event] = 1 THEN 'processed' 
    ELSE 'unprocessed' 
END 

Una cosa che vedo male con il vostro select è il =. È possibile scrivere:

SELECT unprocessed = (CASE WHEN [text_result] IS NOT NULL THEN [text_result] 
          WHEN [last_event] = 1 THEN 'processed' 
          ELSE 'unprocessed' 
         END) 

o

SELECT (CASE WHEN [text_result] IS NOT NULL THEN [text_result] 
      WHEN [last_event] = 1 THEN 'processed' 
      ELSE 'unprocessed' 
     END) as unprocessed 

Ma, quando si utilizza =, la variabile viene prima.

Quindi, non penso che sia possibile specificare un alias di colonna utilizzando ?. Devi costruire la stringa di query con il nome alias della colonna al suo interno.

+0

Il? è il segnaposto per l'input dell'utente passato da un'istruzione preparata, non un alias di colonna? Quindi dovrebbe? vieni prima (ottenendo il risultato "... WHERE 'unprocessed' = (CASE ..)")? – Raiden616

+0

@ user1014679. . . Questo è ciò che intendevo. Non penso che sia possibile specificare un alias di colonna come parametro in un'istruzione preparata. –

+0

"Non elaborato" non è un alias di colonna è un valore ... – Raiden616

0

hai troppi case stataments:

DECLARE @tableA Table 
(
    text_result varchar(20), 
    last_event int 
) 

INSERT INTO @tableA 
VALUES 
    (null, 1), 
    (null, 2), 
    ('xxxx', 3) 

SELECT * 
FROM @tableA 
WHERE 
    CASE WHEN text_result IS NOT NULL THEN text_result 
     WHEN last_event = 1 THEN 'processed' 
    ELSE 'unprocessed' END = 'unprocessed' 
+0

Lo stesso problema si verifica se rimuovo l'istruzione case nidificata (ad esempio' ... WHERE CASE WHEN text_result NON È NULL THEN 'foo' ELSE 'bar' FINE = ?') – Raiden616

+0

Questo funziona:' qry = new MSSQLQuery ("SELECT 'ciao' DOVE 'pippo' = ( \t CASO QUANDO 1 = 1 THEN 'pippo' ELSE 'bar' FINE )"); '. Questo non lo fa: 'qry = new MSSQLQuery ("? SELECT 'ciao' DOVE ( \t CASO QUANDO 1 = 1 THEN 'pippo' ELSE 'bar' FINE ) =", "foo");' – Raiden616

+0

See il mio commento sulla risposta precedente, credo che manchi le virgolette intorno al?. –