string vazia na coluna não-nula no MySQL?
-
06-07-2019 - |
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.
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();