11
votes

MySQL ignore la contrainte non nulle

J'ai créé une table avec NOT NULL contraintes sur certaines colonnes de MySQL. Ensuite, dans PHP, j'ai écrit un script pour insérer des données, avec une requête d'insertion. Lorsque j'étant omettre l'un des colonnes NULL de cette instruction insertion, je m'attendrais à un message d'erreur de MySQL, et je m'attendrais à ce que mon script échoue. Au lieu de cela, MySQL insère des chaînes vides dans les champs non nul . Dans d'autres champs omis, les données sont NULL, qui va bien. Quelqu'un pourrait-il me dire ce que je me suis trompé ici?

J'utilise ce tableau: xxx

et cet instruction insertion: xxx

ou en utilisant des variables de liaison: xxx


0 commentaires

3 Réponses :


5
votes

Ce que vous faites mal consiste à construire votre requête à l'aide de chaînes au lieu d'utiliser des paramètres de liaison.

Misponible de la vulnérabilité d'injection SQL, les valeurs NULL sont converties en cordes vides avant même que la base de données ne les voit. xxx

sorties: xxx

En d'autres termes, vous insérez une chaîne vide, pas une null. Pour insérer une null, vous auriez besoin d'écrire ceci: xxx

si vous utilisez des paramètres de liaison, vous n'obtiendrez pas ce problème et comme bonus que votre site n'aura pas tant de trous de sécurité. Je vous suggère de lire la réponse à Cette question et suivez la conseil là-bas. Cela résoudra votre problème immédiat et améliorera la sécurité de votre site.


1 commentaires

Je dois admettre que l'utilisation de paramètres Bind est meilleure, mais cela ne résout pas encore mon problème. Je vais regarder dans le réglage du mode strict maintenant ...



1
votes

Je suis d'accord avec Mark Byers - Votre PHP est incorrect pour le comportement souhaité.

Re: Le commentaire de Mark sur les paramètres de liaison, consultez PDO en PHP

Si vous ne voulez toujours pas utiliser de paramètres, vous pouvez essayer ce qui suit: < Pré> xxx

EDIT: Avez-vous envisagé simplement de vérifier votre code PHP pour que les valeurs ne soient pas vides / null d'abord? De cette façon, vous pourriez éviter le voyage dans la base de données (basé sur mon interprétation de votre commentaire)? Pas vraiment une réponse au comportement MySQL, mais pourrait trier votre problème.


1 commentaires

"&& $ € Post ['CustomerCompany']! = '' 'Est redondant. Si $ _Post ['CustomPompany'] est une chaîne de longueur zéro, Isset ($ _ Post ['CustomerCompany']) reviendra de faux.



15
votes

Si vous êtes sûr que vous n'utilisez pas de valeurs par défaut explicites, vérifiez votre mode strict: xxx

Type de données MySQL Valeurs par défaut

AS de MySQL 5.0.2, si une colonne la définition ne comprend pas non explicite Valeur par défaut, MySQL détermine le Valeur par défaut comme suit:

Si la colonne peut prendre NULL en tant que valeur, la colonne est définie avec un Clause NULL par défaut explicite. C'est le même que avant 5.0.2.

Si la colonne ne peut pas prendre NULL comme le valeur, mySQL définit la colonne avec Pas de clause par défaut explicite. Pour les données entrée, si une insertion ou remplacer déclaration n'inclut aucune valeur pour le colonne, ou une déclaration de mise à jour des ensembles la colonne à NULL, MySQL gère le colonne selon le mode SQL dans effet à l'époque:

  • Si le mode SQL strict n'est pas activé, MySQL définit la colonne à la Valeur par défaut implicite pour la colonne Type de données.

  • Si le mode strict est activé, une erreur se produit pour les tables transactionnelles. et la déclaration est renvoyée. Pour Tables non transactionnelles, une erreur se produit, mais si cela arrive pour le deuxième rangée ou une rangée ultérieure d'un déclaration à plusieurs lignes, la précédente les rangées auront été insérées.

    Server SQL Modes


4 commentaires

Le mode strict l'a fait! Merci! Au moins, lorsque j'élever une valeur, l'enregistrement n'est pas inséré. Lorsque $ _Post ["CustomerEmail"] est vide, l'enregistrement est toujours inséré, avec une chaîne vide, mais ce n'était pas la portée de cette question. La recherche pour empêcher l'insertion d'une chaîne vide continue.


Pour répondre à votre deuxième question, vous devez utiliser la liaison des paramètres, comme expliqué dans d'autres réponses, mais réfléchissez à cela. Vous n'avez pas besoin '. opérateur de concours pour construire une requête lorsque vous utilisez des guillemets doubles. Vous pouvez faire cela "valeurs ($ client client)". Par conséquent: si (! Vide ($ _ POST ['' CUSTERMINAIMAIL ']) {$ CUSTER CUSTERMAIL = "' $ _POST ['CUSTERMINAIL'] '";} elull {$ CustomerTemail = "Null";};


Merci pour les conseils, j'ai déjà utilisé la liaison des paramètres, lorsque Mark Byers l'a posté, j'ai changé mon code et ... je vérifie déjà le côté PHP, que ce soit vide ou non. Je recherche une vérification de la base de données, comme une contrainte de chèque que j'ai utilisée avec des bases de données Oracle. Pour être honnête: je n'aurais pas besoin d'une contrainte de contrôle en oracle, car une chaîne vide est traitée comme null à Oracle. Une chaîne vide est tout aussi mauvaise pour moi que NULL dans ce cas, alors lorsque je peux toujours insérer une chaîne vide, la contrainte NON NULL est plutôt inutile pour moi. Peut-être que je devrais poster une nouvelle question à ce sujet.


doit noter explicitement comment définir le mode strict