2008-11-30 11 views
2

J'ai utilisé l'extrait suivant dans les développements depuis des années. Maintenant, tout d'un coup, je reçois une erreur de DB: pas de champ d'alarmePourquoi mon INSERT échoue-t-il parfois avec "no such field"?

$process = "process"; 
$create = $connection->query 
(
    "INSERT INTO summery (process) VALUES($process)" 
); 
if (DB::isError($create)) die($create->getMessage($create)); 

mais il est très bien si j'utilise numerics

$process = "12345"; 
$create = $connection->query 
(
    "INSERT INTO summery (process) VALUES($process)" 
); 
if (DB::isError($create)) die($create->getMessage($create)); 

ou écrire directement la valeur dans l'expression

$create = $connection->query 
(
    "INSERT INTO summery (process) VALUES('process')" 
); 
if (DB::isError($create)) die($create->getMessage($create)); 

Je suis vraiment confus ... des suggestions?

+0

Ce serait très utile pour les lecteurs et vous obtiendriez des réponses plus significatives et plus précises si vous fournissiez le nom de l'API DB que vous utilisez. – converter42

+0

Peut-être qu'un fantôme vous taquine de la machine parce que vous avez mal orthographié "résumé". – Svante

Répondre

7

Il est toujours préférable d'utiliser des requêtes préparées et des espaces réservés pour les paramètres. Comme cela en Perl DBI:

my $process=1234; 
my $ins_process = $dbh->prepare("INSERT INTO summary (process) values(?)"); 
$ins_process->execute($process); 

Pour de meilleures performances, préparer toutes vos questions souvent utilisées juste après l'ouverture de la connexion de base de données. Beaucoup de moteurs de bases de données les stockent sur le serveur pendant la session, un peu comme de petites procédures stockées temporaires.

C'est également très bon pour la sécurité. L'écriture de la valeur dans une chaîne d'insertion signifie que vous devez écrire le code d'échappement correct à chaque instruction SQL. Utiliser un style de préparation et d'exécution signifie que seul un place (exécuter) doit savoir échapper, si échapper est même nécessaire.

0

Idem ce que Zan Lynx a dit au sujet des espaces réservés. Mais vous pouvez toujours vous demander pourquoi votre code a échoué.

Il semble que vous ayez oublié un détail crucial du code précédent qui a fonctionné pour vous depuis des années: les citations.

Ce code (testé) fonctionne très bien:

my $thing = 'abcde'; 
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1) 
           VALUES (3,'$thing')"); 
$sth->execute; 

Mais ce code suivant (manque les guillemets dans le champ VALEURS comme votre premier exemple ne) produit l'erreur que vous déclarez parce que les valeurs (3, $ thing) se résout à VALUES (3, abcde), amenant votre serveur SQL à rechercher un champ appelé abcde et il n'y a pas de champ de ce nom.

my $thing = 'abcde'; 
my $sth = $dbh->prepare("INSERT INTO table1 (id,field1) 
           VALUES (3,$thing)"); 
$sth->execute; 

Tout cela suppose que votre premier exemple n'est pas une citation directe de code qui n'a pas que vous décrivez et donc pas ce que vous vouliez. Il décide de:

"INSERT INTO summery (process) VALUES(process)" 

qui, comme mentionné ci-dessus provoque votre serveur SQL pour lire l'article dans les valeurs définies comme un autre nom de domaine. Comme indiqué, ceci fonctionne réellement sur MySQL sans se plaindre et remplira le champ appelé 'process' avec NULL car c'est ce que le champ appelé 'process' contenait quand MySQL cherchait là une valeur lors de la création du nouvel enregistrement. J'utilise ce style pour les piratages rapides impliquant des données connues et sécurisées (par exemple, une valeur fournie dans le programme lui-même). Mais pour tout ce qui concerne des données provenant de l'extérieur du programme ou qui pourraient contenir autre chose que [0-9a-zA-Z], cela vous évitera d'utiliser des espaces réservés.