2014-10-09 18 views
5

Utilizzando Postgres 9.3:Postgres Regole Prevenzione CTE query

Sto tentando di compilare automaticamente un tavolo quando un inserimento viene eseguito su un altro tavolo. Questo mi sembra un buon uso per le regole, ma dopo aver aggiunto la regola alla prima tabella, non sono più in grado di eseguire inserimenti nella seconda tabella utilizzando il CTE scrivibile. Ecco un esempio:

CREATE TABLE foo (
    id INT PRIMARY KEY 
); 

CREATE TABLE bar (
    id INT PRIMARY KEY REFERENCES foo 
); 

CREATE RULE insertFoo AS ON INSERT TO foo DO INSERT INTO bar VALUES (NEW.id); 

WITH a AS (SELECT * FROM (VALUES (1), (2)) b) 
INSERT INTO foo SELECT * FROM a 

Quando questo viene eseguito, ottengo l'errore

"ERROR: WITH cannot be used in a query that is rewritten by rules into multiple queries".

Ho cercato per quella stringa di errore, ma sono solo in grado di trovare i link al codice sorgente. So che posso eseguire il suddetto uso di trigger a livello di riga, ma sembra che dovrei essere in grado di farlo a livello di istruzione. Perché non è possibile utilizzare la scrittura CTE, quando le query come questo può (in questo caso) essere facilmente ri-scritte come:

INSERT INTO foo SELECT * FROM (VALUES (1), (2)) a 

Qualcuno sa di un altro modo che realizzare quello che sto cercando di fare altro che 1) utilizzando le regole, che impedisce l'utilizzo di query "con" o 2) utilizzando i trigger a livello di riga? Grazie,

+3

Perché non si desidera utilizzare un trigger? –

+0

La mia esperienza nel database è di circa 5 mesi, quindi ogni volta che mi imbatto in un problema che non riesco a capire una soluzione mi piace molto, immagino che dovrei chiedere agli esperti in modo da poter conoscere le varie opzioni. Per qualcosa di così semplice, una regola sembrava la strada da percorrere per motivi di prestazioni, ma non mi piace il limite di non essere in grado di utilizzare il CTE scrivibile nelle query. –

+0

Devo aggiungere che sto pensando di utilizzare i trigger a livello di riga come soluzione, a meno che qualcuno non fornisca un'alternativa migliore qui a SO. –

risposta

3

TL; DR: utilizza i trigger, non le regole.

In generale, preferiscono i trigger rispetto alle regole, a meno che le regole non siano assolutamente necessarie. (Che, in pratica, non lo sono mai.)

L'utilizzo delle regole introduce un sacco di problemi che complicheranno inutilmente la tua vita lungo la strada. Ne hai incontrato uno qui. Un altro (maggiore) è, ad esempio, che il numero di righe interessate corrisponderà a quello dell'ultima query, se si sta facendo affidamento su FOUND da qualche parte e la query riporta erroneamente che nessuna riga è stata interessata da una query, sarai in cerca di insetti dolorosi.

Inoltre, c'è occasionale parla di deprecando Postgres regole a titolo definitivo:

http://postgresql.nabble.com/Deprecating-RULES-td5727689.html