2009-11-30 11 views
1

PostgreSQL 8.4 sous Linux. J'ai une fonction:Problème PostgreSQL avec des arguments nommés dans une fonction

CREATE OR REPLACE FUNCTION production.add_customer ( 
name varchar(100), 
email_address varchar(300), 
street_address text, 
city varchar(50), 
state varchar(2), 
zip varchar(10), 
secret1 bytea, 
secret2 bytea, 
secret3 bytea, 
secret4 bytea, 
referrer text) 
RETURNS integer as $$ 
BEGIN 
INSERT INTO customers (name, email_address, street_address, city, state, zip, secret1, secret2, secret3, secret4, create_date, referrer) VALUES 
(name, email_address, street_address, city, state, zip, create_date, referrer 
pgp_sym_encrypt(secret1, 'reallylongrandomstring'), 
pgp_sym_encrypt(secret2, 'reallylongrandomstring'), 
pgp_sym_encrypt(secret3, 'reallylongrandomstring'), 
pgp_sym_encrypt(secret4, 'reallylongrandomstring'), 
current_timestamp, referrer); 
RETURNING customer_id; 
END; 
$$ LANGUAGE plpgsql; 

qui retourne cette erreur lorsque je tente une créer:

ERROR: syntax error at or near "$1" 
LINE 1: INSERT INTO customers ($1 , $2 , $3 , $4 , $5 , $6 , ... 
          ^
QUERY: INSERT INTO customers ($1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 , $9 , $10 , create_date, $11) VALUES ($1 , $2 , $3 , $4 , $5 , $6 , create_date, $11 pgp_sym_encrypt($7 , 'reallylongrandomstring'), pgp_sym_encrypt($8 , 'reallylongrandomstring'), pgp_sym_encrypt($9 , 'reallylongrandomstring'), pgp_sym_encrypt($10 , 'reallylongrandomstring'), current_timestamp, $11) 
CONTEXT: SQL statement in PL/PgSQL function "add_customer" near line 8 
myserver=# 

J'ai essayé ALIAS FOR, pas de chance. Des idées?

Répondre

3

Vos arguments portent le même nom que les colonnes du INSERT; PL/pgSQL substitue incorrectement tous les deux ensembles d'identificateurs (colonnes et valeurs) avec l'argument, se terminant par le INSERT absurde que vous voyez dans l'erreur.

Voir le Attention section sur this page pour le mot officiel - mais vous aurez essentiellement besoin de changer les noms des arguments.

+0

Cela a résolu mon problème. Ça sent un peu bête non? Oracle ou SQL Server n'ont aucun problème avec ce format. Merci beaucoup SimonJ! – Craig

+0

Je ne suis pas sûr qu'ils considèrent cela comme un bug, étant donné la quantité de discussions consacrées au sujet dans les docs. Si rien d'autre, il encourage les bonnes pratiques en forçant des noms qui ne se chevauchent pas! – SimonJ

+0

Oh, et il est tout à fait possible d'entrer dans un désordre similaire (mais peut-être plus subtil) avec Oracle - j'ai vu des requêtes innocentes 'SELECT' brisées quand quelqu'un a introduit une variable locale avec le même nom qu'une colonne, ou vice versa... – SimonJ

0

name est un mot-clé réservé dans PostgreSQL.

Modifier à INSERT INTO customers ("name", etc etc...

aussi ce qu'il a dit: tous les précédez noms des variables avec un _ ou similaire.

1

Ce comportement sera modifié dans PostgreSQL 9.0.

a) PostgreSQL 9.0 est plus intelligent et applique uniquement des variables aux bons endroits

b) La priorité est facultative - comme PostgreSQL, comme Oracle ou relancer exception

Pour préfixe plus de l'utilisation de la version pour toutes les variables locales et paramètres dans toutes les fonctions avec SQL intégré.