Pergunta

Eu costumava usar o mysql_connect padrão (), mysql_query (), etc declarações para fazer coisas MySQL do PHP. Ultimamente eu tenho mudar para usando a classe MDB2 maravilhoso. Junto com ele, eu estou usando declarações preparadas, por isso não precisa se preocupar em escapar minha entrada e ataques de injeção SQL.

No entanto, há um problema eu estou correndo em. I têm uma tabela com algumas colunas VARCHAR, que são especificados como não-nulo (isto é, não permitem valores nulos). Usando os comandos antigos MySQL PHP, eu poderia fazer coisas como esta, sem qualquer problema:

INSERT INTO mytable SET somevarchar = '';

Agora, no entanto, se eu tiver uma consulta como:

INSERT INTO mytable SET somevarchar = ?;

E, em seguida, em PHP eu tenho:

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

Isto irá lançar o erro "null value violates not-null constraint"

Como solução temporária, posso verificar se $value está vazio, e alterá-lo para " " (um único espaço), mas isso é um hack horrível e pode causar outros problemas.

Como é que eu vou inserir cadeias vazias com declarações preparadas, sem ele tentando, em vez inserir um NULL?

EDIT: É muito grande de um projeto que passar por toda a minha base de código, encontrar todos os lugares que utiliza uma cadeia vazia "" e alterá-lo para usar NULL vez. O que eu preciso saber é por consultas padrão do MySQL tratar "" e NULL como duas coisas separadas (como eu acho que é correto), mas declarações preparadas convertidos "" para NULL.

Note que "" e NULL são não a mesma coisa. Por exemplo, retorna SELECT NULL = ""; NULL vez de 1 como seria de esperar.

Foi útil?

Solução

Isso soa como um problema com a API MDB2 desastrado semântica pato digitação do PHP. Uma vez que a cadeia vazia em PHP é equivalente a NULL, MDB2 é provavelmente mis-tratá-la como tal. A solução ideal seria encontrar uma solução para isso dentro dele de API, mas eu não estou muito familiarizado com ele.

Uma coisa que você deve considerar, porém, é que uma cadeia vazia no SQL não é um valor NULL. Você pode inseri-los em linhas declarou 'NOT NULL' muito bem:

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 você é incapaz de encontrar (ou implementar) uma solução alternativa na API MDB2, uma solução hackish (embora ligeiramente melhor do que o que você está usando atualmente) pode definir uma variável de usuário para a cadeia vazia -

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

Finalmente, se você precisa usar a cadeia vazia em uma instrução INSERT, mas encontrar-se incapaz de, o valor padrão para tipos string no MySQL é uma cadeia vazia. Então, você poderia simplesmente omitir a coluna de instrução INSERT e seria automaticamente prepare-se para a cadeia vazia (desde que a coluna tem um NULL restrição NOT).

Outras dicas

Graças a algumas das respostas, percebi que o problema pode estar na API MDB2, e não no PHP ou MySQL comandos si. o suficiente certeza, eu encontrei isso no MDB2 FAQ:

  • Por que strings vazias acabar como NULL no banco de dados? Por que recebo um NULL não permitido em campos de texto não NULL mesmo admitindo que o valor padrão é ""?
    • O problema é que, para alguns RDBMS (mais noteably Oracle) um vazio string é NULL. portanto MDB2 oferece uma opção de portabilidade para aplicar o mesmo comportamento em todos RDBMS.
    • Uma vez que todas as opções de portabilidade são ativadas por padrão você terá para desativar o recurso se você não quer ter este comportamento: $ Mdb2-> setOption ( 'portabilidade', MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);

Obrigado a todos que forneceram respostas atenciosas.

Eu percebo esta pergunta é muito bonito respondeu e retirou-se, mas eu achei enquanto procurava respostas para uma situação semelhante e eu não posso resistir jogar meu chapéu no anel.

Sem saber o que o NULL / "" coluna refere-se, eu não posso saber como o verdadeiro significado de uma cadeia vazia. Será string vazia média em si mesmo (como, se eu convenci um juiz para deixar-me mudar meu nome para simplesmente nada, eu estaria muito irritado se meu nome apareceu na minha carteira de motorista como NULL alguma coisa. Meu nome seria!

No entanto, a cadeia vazia (ou branco, ou o nada que é algo, não simplesmente a falta de qualquer coisa (como NULL)) também poderia simplesmente média "NOT NULL" ou "Nada, mas ainda não é nulo". Você poderia até mesmo ir a outra direção e sugerem que a ausência do valor NULL faz algo ainda menos do que nulo, porque pelo menos nulo tem um nome que você pode dizer em voz alta!

O meu ponto é que, se a cadeia vazia é uma representação direta de alguns dados (como um nome, ou o que eu prefiro ser inserido entre os números em meu número de telefone, etc), então suas opções são ou a discutir até que você 'sore re para o uso legítimo da cadeia vazia ou para uso algo que representa uma cadeia vazia que não é NULL (como um caractere de controle ASCII ou algum unicode equivalente, um valor regex de algum tipo, ou, pior ainda, uma arbitrariedade ainda totalmente símbolo não utilizado, como: ?

Se a célula vazia realmente significa apenas NOT NULL, então você poderia pensar em alguma outra maneira de expressá-la. Uma maneira tola e óbvia é a frase "Não NULL". Mas eu tenho um palpite de que NULL significa algo como "Não faz parte deste grupo em tudo", enquanto o meio string vazia algo como "esse cara é legal, ele simplesmente não tem obtido suas tatuagens de gangue ainda". Caso em que eu iria chegar a um termo / nome / ideia para esta situação, como "default" ou "rookie" ou "pendente".

Agora, se por algum acaso louco você realmente quer string vazia para representar aquilo que não é sequer digno de NULL, mais uma vez, chegar a um símbolo mais significativo para que, como "-1" ou "SUPERNULL" ou " feias".

No sistema de castas indiano, a casta mais baixa são Shudra: fazendeiros e trabalhadores. Abaixo desta casta são os Dalit: "Os Intocáveis". Eles não são considerados uma casta inferior, porque definindo-as como a casta mais baixa seria considerada uma contaminação de todo o sistema.

Portanto, não me chame de louco por pensar cadeias vazias pode ser pior do que NULL!

'Til da próxima vez.

Eu encontrei a solução!

Converte mdb2 cadeias vazias para NULL porque a opção portabilidade MDB2_PORTABILITY_EMPTY_TO_NULL é ativado por padrão (graças a Oracle, que considera cadeias vazias para ser nulo).

Mudar esta opção off quando você se conectar ao banco de dados:

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

Enquanto 0 e vazios cordas são variáveis ??NULL é a ausência de dados. E confiem em mim, é muito mais fácil de escrever uma consulta para

SELECT * from table where mything IS NULL do que tentar consulta para cadeias vazias: /

não um conjunto vazio de citações, "" fazer isso?

Estou confuso. Parece que você está usando OO mysqli (a partir das tags e estilo), mas a sintaxe é diferente do que o rel manual sobre php.net, que diz para fazer isso em vez disso:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top