2008-11-05 14 views
11

Ho usato le istruzioni standard mysql_connect(), mysql_query(), ecc per fare cose MySQL da PHP. Ultimamente sto passando ad usare la meravigliosa classe MDB2. Insieme a questo, sto usando le istruzioni preparate, quindi non devo preoccuparmi di sfuggire al mio input e agli attacchi di SQL injection.Stringa vuota nella colonna non nullo in MySQL?

Tuttavia, c'è un problema che sto incontrando. Ho una tabella con alcune colonne VARCHAR, che sono specificate come not-null (cioè, non consentono valori NULL). Utilizzando i comandi vecchio MySQL PHP, ho potuto fare cose come questa senza alcun problema:

INSERT INTO mytable SET somevarchar = ''; 

Ora, però, se ho una domanda come:

INSERT INTO mytable SET somevarchar = ?; 

E poi in PHP che ho:

$value = ""; 
$prepared = $db->prepare($query, array('text')); 
$result = $prepared->execute($value); 

Questo getterà l'errore "null value violates not-null constraint"

Come soluzione temporanea, I c diamine se $value è vuoto, e cambialo su " " (un singolo spazio), ma è un trucco orribile e potrebbe causare altri problemi.

Come dovrei inserire stringhe vuote con istruzioni preparate, senza provare a inserire un NULL?

EDIT: E 'troppo grande di un progetto di passare attraverso il mio intero codebase, trovare ovunque che utilizza una stringa vuota "" e cambiare in modo da utilizzare al posto NULL. Quello che devo sapere è perché le query standard di MySQL considerano "" e NULL come due cose separate (come penso sia corretto), ma le istruzioni preparate convergono "" in NULL.

Nota che "" e NULL sono non la stessa cosa. Ad esempio, SELECT NULL = ""; restituisce NULL anziché 1 come previsto.

+1

Se si inserisce "", che è fondamentalmente nulla, perché non cambiare il campo nel db per consentire null. – UnkwnTech

+6

è "fondamentalmente nulla" nello stesso modo in cui 0 è "fondamentalmente" falso. sono simili ma in realtà abbastanza diversi. – nickf

+1

NULL significa "nessun valore" no, "stringa vuota" – warren

risposta

11

Questo suona come un problema di l'API MDB2 armeggia nella semantica della tipizzazione di anatra di PHP. Poiché la stringa vuota in PHP è equivalente a NULL, MDB2 probabilmente la considera erroneamente come tale. La soluzione ideale sarebbe trovare una soluzione alternativa all'interno della sua API, ma non ne ho una conoscenza eccessiva.

Una cosa da considerare, tuttavia, è che una stringa vuota in SQL non è un valore NULL.È possibile inserirli in file dichiarati 'NOT NULL' bene:

mysql> CREATE TABLE tbl(row CHAR(128) NOT NULL); 
Query OK, 0 rows affected (0.05 sec) 

mysql> INSERT INTO tbl VALUES('not empty'), (''); 
Query OK, 2 rows affected (0.02 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> SELECT row, row IS NULL FROM tbl; 
+-----------+-------------+ 
| row  | row IS NULL | 
+-----------+-------------+ 
| not empty |   0 | 
|   |   0 | 
+-----------+-------------+ 
2 rows in set (0.00 sec) 

mysql> INSERT INTO tbl VALUES(NULL); 
ERROR 1048 (23000): Column 'row' cannot be null 

Se non sei in grado di trovare (o implementare) una soluzione nell'API MDB2, una soluzione hacker (anche se leggermente migliore di quello che si attualmente sei usando) potrebbe essere quella di definire un user variable per la stringa vuota -

SET @EMPTY_STRING = ""; 
UPDATE tbl SET [email protected]_STRING; 

Infine, se è necessario utilizzare la stringa vuota in un'istruzione INSERT, ma trovare te stesso in grado di, il valore di default per i tipi di stringhe in MySQL è una stringa vuota. Quindi potresti semplicemente omettere la colonna dall'istruzione INSERT e verrà automaticamente impostata sulla stringa vuota (a condizione che la colonna abbia un vincolo NOT NULL).

+0

Questo era, non pensavo che MDB2 potesse essere il colpevole. Grazie. – davr

0

Non fa una serie vuota di preventivi, ""?

+0

No, "" e NULL sono cose diverse e si comportano in modo diverso nella maggior parte dei database. – davr

+0

@davr - esattamente per questo ho detto di farlo - sta cercando di ottenere un valore NOT NULL nel db, che le virgolette vuote sono – warren

-1

Sono confuso. Sembra che si sta utilizzando mysqli OO (dai tag e lo stile), ma la sintassi è diverso da quello del manual su php.net, che dice di fare questo, invece:

$query = "INSERT INTO mytable SET somevarchar = ?"; 
$value = ""; 
$prepared = $db->prepare($query); 
$prepared->bind_param("s", $value); 
$result = $prepared->execute(); 
+0

Sto usando MDB2, che usa mysqli internamente. – davr

17

Grazie ad alcune delle risposte, ho capito che il problema potrebbe essere nell'API MDB2 e non nei comandi PHP o MYSQL. Abbastanza sicuro, ho trovato questo nella MDB2 FAQ:

  • Perché le stringhe vuote finire come NULL nel database? Perché viene visualizzato un valore NULL non consentito nei campi di testo NOT NULL sebbene il valore predefinito sia ""?
    • Il problema è che per alcuni RDBMS (in particolare per Oracle) una stringa vuota è NULL. Pertanto MDB2 fornisce un'opzione di portabilità a e applica lo stesso comportamento a tutti gli RDBMS .
    • Poiché tutte le opzioni di portabilità sono abilitate di default si dovrà di disattivare la funzione se non desidera avere questo comportamento: $ mdb2-> setOption ('portabilità', MDB2_PORTABILITY_ALL^​​ MDB2_PORTABILITY_EMPTY_TO_NULL);

Grazie a tutti coloro che hanno fornito risposte riflessivo.

2

Mi rendo conto che questa domanda è praticamente risposta e ritirata, ma l'ho trovata mentre cercavo risposte a una situazione simile e non posso resistere a lanciare il mio cappello sul ring.

Senza sapere a che cosa si riferisce la colonna NULL/"", non posso sapere quale sia il vero significato di una stringa vuota. La stringa vuota significa qualcosa a se stessa (come se convincessi un giudice a farmi cambiare nome semplicemente a nulla, sarei davvero irritato se il mio nome comparisse nella mia patente di guida come NULL. Il mio nome sarebbe!

Tuttavia, la stringa vuota (o vuota, o il nulla che è QUALCOSA, non semplicemente la mancanza di qualsiasi cosa (come NULL) potrebbe anche semplicemente significare "NOT NULL" o "Nothing, but still not Null". vai nella direzione opposta e suggerisci che l'assenza del valore NULL rende ANCORA MENO qualcosa rispetto a Null, perché almeno Null ha un nome che puoi pronunciare ad alta voce!

Il mio punto è che se la stringa vuota è una rappresentazione diretta di alcuni dati (come un nome, o quello che preferisco essere inserito tra i numeri nel mio numero di telefono, ecc.), Allora le tue opzioni sono o di discutere fino a sei dolorante per l'uso legittimo di una stringa vuota o per utilizzare qualcosa che rappresenta una stringa vuota che non è NULL (come un carattere di controllo ASCII o un equivalente unicode, un valore regex di qualche tipo o, peggio ancora, un arbitrario token completamente inutilizzati, come: ◘

Se la cella vuota significa solo NON ANCORA, allora potresti pensare ad un altro modo di esprimerlo.Un modo stupido e ovvio è la frase "Not NULL". l'impressione che NULL significhi qualcosa come "Non fa parte di questo gruppo" mentre la stringa vuota significa qualcosa come "questo ragazzo è forte, non ha ancora ottenuto i suoi tatuaggi di gruppo". In tal caso, vorrei trovare un termine/nome/idea per questa situazione, come "default" o "rookie" o "In attesa".

Ora, se per qualche pazzo caso si desidera effettivamente che la stringa vuota rappresenti ciò che non è nemmeno degno di NULL, di nuovo, si presenta con un simbolo più significativo, ad esempio "-1" o "SUPERNULL" o "Brutti".

Nel sistema di caste indiano, le caste più basse sono Shudra: agricoltori e lavoratori. Sotto questa casta sono i Dalit: "Gli intoccabili". Non sono considerati una casta inferiore, perché considerarli come la casta più bassa sarebbe considerata una contaminazione dell'intero sistema.

Quindi non chiamarmi pazzo per il pensiero che le stringhe vuote potrebbero essere PEGGIOSE di NULL!

'Alla prossima volta.

1

Ho trovato la soluzione!

MDB2 converte stringhe vuote in NULL perché l'opzione di portabilità MDB2_PORTABILITY_EMPTY_TO_NULL è attivata per impostazione predefinita (grazie a Oracle che considera le stringhe vuote da null).

attivare questa opzioni fuori quando ci si connette al database:

$options = array(
    'portability' => MDB2_PORTABILITY_ALL^MDB2_PORTABILITY_EMPTY_TO_NULL 
); 
$res= & MDB2::connect("mysql://user:[email protected]/dbase", $options); 
+0

uhm ... Ho scritto questa risposta esatta più di un anno fa. – davr

+0

Oops :-) Non me ne sono accorto. – ahhon

1

Mentre 0 e vuoti stringhe sono variabili NULL è l'assenza di dati. E, credetemi, è molto più facile scrivere una query per

SELECT * from table where mything IS NULL che cercare di query per le stringhe vuote:/