Domanda

Usavo le istruzioni mysql_connect (), mysql_query (), ecc. standard per fare cose MySQL da PHP. Ultimamente sono passato all'utilizzo della meravigliosa classe MDB2. Insieme ad esso, sto usando istruzioni preparate, quindi non devo preoccuparmi di sfuggire al mio input e agli attacchi di iniezione SQL.

Tuttavia, sto riscontrando un problema. Ho una tabella con alcune colonne VARCHAR, che sono specificate come non-null (ovvero, non consentono valori NULL). Usando i vecchi comandi MySQL PHP, ho potuto fare queste cose senza alcun problema:

INSERT INTO mytable SET somevarchar = '';

Ora, tuttavia, se ho una domanda come:

INSERT INTO mytable SET somevarchar = ?;

E poi in PHP ho:

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

Questo genererà l'errore " il valore null viola il vincolo non null "

Come soluzione temporanea, controllo se $ value è vuoto e lo cambio in " " (un singolo spazio), ma è un trucco orribile e potrebbe causare altri problemi.

Come posso inserire stringhe vuote con istruzioni preparate, senza che cerchi invece di inserire un NULL?

EDIT: È un progetto troppo grande per passare attraverso la mia intera base di codice, trovare ovunque che usi una stringa vuota " " e cambiarlo per usare invece NULL. Quello che devo sapere è perché le query MySQL standard trattano " " e NULL come due cose separate (come penso sia corretto), ma le istruzioni preparate convertono " " in NULL.

Nota che " " e NULL non sono non la stessa cosa. Ad esempio, SELECT NULL = " " ;; restituisce NULL invece di 1 come ti aspetteresti.

È stato utile?

Soluzione

Questo sembra un problema con l'API MDB2 che altera la semantica della tipizzazione delle papere di PHP. Poiché la stringa vuota in PHP è equivalente a NULL, MDB2 probabilmente la sta trattando in modo errato come tale. La soluzione ideale sarebbe quella di trovare una soluzione alternativa all'interno della sua API, ma non ho troppa familiarità con esso.

Una cosa da considerare, tuttavia, è che una stringa vuota in SQL non è un valore NULL. Puoi inserirli nelle righe dichiarate "NOT NULL" (OK NULL):

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 riesci a trovare (o implementare) una soluzione alternativa nell'API MDB2, una soluzione di hacking (sebbene leggermente migliore di quella che stai attualmente utilizzando) potrebbe essere quella di definire un variabile utente per la stringa vuota -

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

Infine, se devi usare la stringa vuota in un'istruzione INSERT ma non riesci a farlo, il valore predefinito per i tipi di stringa in MySQL è una stringa vuota. Quindi potresti semplicemente omettere la colonna dall'istruzione INSERT e verrebbe automaticamente impostata sulla stringa vuota (a condizione che la colonna abbia un vincolo NOT NULL).

Altri suggerimenti

Grazie ad alcune delle risposte, mi sono reso conto che il problema potrebbe essere nell'API MDB2 e non nei comandi PHP o MYSQL stessi. Abbastanza sicuro, ho trovato questo nelle FAQ MDB2:

  
      
  • Perché le stringhe vuote finiscono come NULL nel database? Perché ottengo un NULL   non consentito nei campi di testo NON NULL   sebbene il valore predefinito sia " " ;?      
        
    • Il problema è che per alcuni RDBMS (soprattutto Oracle) un vuoto   stringa è NULL. Pertanto MDB2   fornisce un'opzione di portabilità a   applicare lo stesso comportamento a tutti   RDBMS.
    •   
    • Poiché tutte le opzioni di portabilità sono abilitate per impostazione predefinita, avrai   per disabilitare la funzione se non lo fai   vuole avere questo comportamento:   $ Mdb2- > setOption ( 'portabilità',   MDB2_PORTABILITY_ALL ^   MDB2_PORTABILITY_EMPTY_TO_NULL);
    •   
  •   

Grazie a tutti coloro che hanno fornito risposte ponderate.

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

Senza sapere cosa è il NULL / " " colonna si riferisce a, non posso sapere come il vero significato di una stringa vuota. La stringa vuota significa qualcosa di per sé (come se avessi convinto un giudice a farmi cambiare il mio nome in semplicemente nulla, sarei davvero irritato se il mio nome comparisse sulla 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 qualcosa (come NULL)) potrebbe anche semplicemente significare " NOT NULL " o "Niente, ma comunque non Nullo". Potresti anche andare nell'altra direzione e suggerire che l'assenza del valore NULL lo rende anche MENO qualcosa di Null, perché almeno Null ha un nome che puoi dire 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 quando tu sei dolorante per l'uso legittimo di una stringa vuota o per usare 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 ancora token totalmente inutilizzato, come: & # 9688;

Se la cella vuota significa davvero NON NULL, allora potresti pensare ad un altro modo di esprimerla. Un modo sciocco e ovvio è la frase "Not NULL". Ma ho la sensazione che NULL significhi qualcosa del tipo " Non fa parte di questo gruppo " mentre la stringa vuota significa qualcosa come " questo ragazzo è figo, non ha ancora ottenuto i suoi tatuaggi di gang " ;. In tal caso, mi viene in mente un termine / nome / idea per questa situazione, come "predefinito". o "rookie" o " In sospeso " ;.

Ora, se per una folle occasione vuoi davvero che una stringa vuota rappresenti ciò che non è nemmeno degno di NULL, di nuovo, trovi un simbolo più significativo per questo, come " -1 " o " SUPERNULL " o " UGLIES " ;.

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

Quindi non chiamarmi pazzo per pensare che le stringhe vuote possano essere PEGGIORI di NULL!

'Alla prossima.

Ho trovato la soluzione!

MDB2 converte le 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 come nulle).

Disattiva queste opzioni quando ti connetti al database:

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);

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

SELEZIONA * dalla tabella dove NULL È NULL piuttosto che provare a cercare stringhe vuote: /

Un insieme vuoto di virgolette, " " non lo fa?

Sono confuso. Sembra che tu stia usando mysqli OO (dai tag e dallo stile), ma la sintassi è diversa dalla manual su php.net, che dice invece di fare questo:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top