2010-03-23 17 views
8

He creado una tabla con NOT NULL restricciones en algunas columnas en MySQL. Luego en PHP escribí un script para insertar datos, con una consulta de inserción. Cuando omito una de las columnas NOT NULL en esta instrucción de inserción, esperaría un mensaje de error de MySQL, y esperaría que mi secuencia de comandos fallara. En cambio, MySQL inserta cadenas vacías en los campos NOT NULL. En otros campos omitidos, los datos son NULL, lo cual está bien. ¿Podría alguien decirme qué hice mal aquí?MySQL ignora la restricción NOT NULL

estoy usando esta tabla:

CREATE TABLE IF NOT EXISTS tblCustomers (
    cust_id int(11) NOT NULL AUTO_INCREMENT, 
    custname varchar(50) NOT NULL, 
    company varchar(50), 
    phone varchar(50), 
    email varchar(50) NOT NULL, 
    country varchar(50) NOT NULL, 
    ... 
    date_added timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (cust_id) 
) ; 

Y esta instrucción de inserción:

$sql = "INSERT INTO tblCustomers (custname,company) 
     VALUES ('".$customerName."','".$_POST["CustomerCompany"]."')"; 
$res = mysqli_query($mysqli, $sql); 

o el uso de variables de enlace:

$stmt = mysqli_prepare($mysqli, "INSERT INTO tblCustomers (custname,company, email, country) VALUES (?, ?, ?, ?)"); 

mysqli_stmt_bind_param($stmt, 'ssss', $customerName, $_POST["CustomerCompany"], $_POST["CustomerEmail"], $_POST["AddressCountry"]); 
mysqli_stmt_execute($stmt); 
mysqli_stmt_close($stmt); 

Respuesta

14

Si está seguro de que no está utilizando los valores por defecto explícitas, a continuación, comprobar su modo estricto:

SELECT @@GLOBAL.sql_mode; 
SELECT @@SESSION.sql_mode; 

MySQL Data Type Default Values

En MySQL 5.0.2, si una definición de columna incluye ningún valor explícito DEFAULT, MySQL determina el valor por defecto como sigue:

Si la columna puede tomar NULL como un valor , la columna se define con una cláusula NULL DEFAULT explícita. Esto es lo mismo que antes 5.0.2.

Si la columna no puede tomar NULL como el valor , MySQL define la columna con sin una cláusula DEFAULT explícita. Para los datos entrada, si un insertar o sustituir declaración incluye ningún valor para la columna de , o una instrucción UPDATE establece la columna a NULL, MySQL trata la columna de la acuerdo con el modo SQL en vigor en el momento:

  • Si el modo SQL estricto no está habilitado, MySQL establece la columna en el valor predeterminado implícito para el tipo de datos de columna .

  • Si el modo estricto está habilitado, se produce un error para las tablas transaccionales y la declaración se retrotrae. Para las tablas no transaccionales , se produce un error , pero si esto ocurre para la segunda o subsecuente fila de una instrucción de múltiples filas , las filas anteriores se habrán insertado.

Server SQL Modes

+0

¡El modo estricto lo hizo! ¡Gracias! Al menos cuando omito un valor, el registro no se inserta. Cuando $ _POST ["CustomerEmail"] está vacío, el registro aún se inserta, con una cadena vacía, pero ese no era el alcance de esta pregunta. La búsqueda para evitar la inserción de una cadena vacía continúa. – Whakkee

+0

Para responder a su segunda pregunta, entonces, debe usar el enlace de parámetros, como se explica en otras respuestas, pero piense en esto. No necesitas '.' operador concat para generar consultas cuando se utilizan comillas dobles. Puede hacer esto "VALUES ($correoelectrónicode cliente)". Por lo tanto: if (! Empty ($ _ POST ['CustomerEmail']) {$ customerEmail = "'$ _POST [' CustomerEmail ']'";} else {$ customerEmail = "NULL";} –

+0

Gracias por el consejo, ya utilicé el enlace de parámetros, cuando Mark Byers lo publicó, cambié mi código y ... ya comprobé en el lado php si está vacío o no. Estoy buscando una verificación de la base de datos, como una restricción de verificación que utilicé con bases de datos Oracle Para ser sincero: no necesitaría una restricción de verificación en Oracle, ya que una cadena vacía se trata como NULL en Oracle. Una cadena vacía es tan mala para mí como NULL en este caso, por lo que cuando aún puedo insertar una vacía cadena, la restricción NOT NULL es bastante inútil para mí. Tal vez debería publicar una nueva pregunta sobre esto. – Whakkee

4

Lo que está haciendo mal está la construcción de su consulta utilizando cadenas en lugar de usar parámetros de enlace.

Aparte de la vulnerabilidad de inyección SQL, los valores nulos se están convirtiendo en cadenas vacías incluso antes de que la base de datos los vea.

$x = null; 
print_r("VALUES ('$x', 42)"); 

Salidas:

VALUES ('', 42) 

En otras palabras, va a insertar una cadena vacía, no un NULL. Para insertar un valor NULL que habría necesitado para escribir esto:

VALUES (NULL, 42) 

Si utiliza parámetros se unen entonces no obtendrá este problema y como un bono su sitio no tendrá tantos agujeros de seguridad. Le sugiero que lea la respuesta al this question y siga los consejos allí. Esto resolverá su problema inmediato y mejorará la seguridad de su sitio.

+0

he de reconocer que el uso de parámetros BIND es mejor, pero no resuelve mi problema todavía. Examinaré la configuración del modo estricto ahora ... – Whakkee

1

Estoy de acuerdo con Mark Byers: su php es incorrecto para el comportamiento que desea.

Re: comentario de Mark en parámetros de unión, echa un vistazo a PDO in PHP

Si todavía no desea utilizar los parámetros, puede probar lo siguiente:


if (isset($customerName) && $customerName != '') 
{ 
    $c = '\'' . $customerName . '\''; 
} else { 
    $c = 'null'; 
} 

if (isset($_POST['CustomerCompany']) && $_POST['CustomerCompany'] != '') 
{ 
    $cc = '\'' . $_POST['CustomerCompany'] . '\''; 
} else { 
    $cc = 'null'; 
} 

$sql = 'INSERT INTO tblCustomers (custname,company) 
     VALUES ('.$c.','.$cc.')'; 

Editar: ¿Ha considerado ¿simplemente revisando su código PHP para asegurarse de que los valores no estén en blanco/nulos primero? De esa forma, podrías evitar el viaje a la base de datos (según mi interpretación de tu comentario). No es realmente una respuesta al comportamiento de MySQL, pero podría resolver su problema.

+0

"&& $ _POST ['CustomerCompany']! = ''" Es redundante. si $ _POST ['CustomerCompany'] es una cadena de longitud cero, isset ($ _ POST ['CustomerCompany']) devolverá false. – jmucchiello

Cuestiones relacionadas