mysql – cita numeri o no?

Ad esempio: creo database e una tabella da cli e inserisco alcuni dati:

CREATE DATABASE testdb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; USE testdb; CREATE TABLE test (id INT, str VARCHAR(100)) TYPE=innodb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; INSERT INTO test VALUES (9, 'some string'); 

Ora posso fare questo e questi esempi funzionano (quindi le virgolette non influenzano nulla):

 SELECT * FROM test WHERE id = '9'; INSERT INTO test VALUES ('11', 'some string'); 

Quindi – in questi esempi ho selezionato una riga con una stringa che effettivamente è stata memorizzata come INT in mysql e poi ho inserito una stringa in una colonna che è INT.

Non capisco perché funziona così come funziona qui. Perché la stringa può essere inserita in una colonna INT?

Posso inserire tutti i tipi di dati Mysql come stringhe?

    Questo comportamento è standard su diversi RDBMS?

    Grazie!

    MySQL è molto simile a PHP e converte automaticamente i tipi di dati nel miglior modo ansible. Dato che stai lavorando con un campo int (lato sinistro), proverà a convertire in modo trasparente il lato destro dell’argomento in un int, quindi '9' diventa solo 9 .

    A rigor di termini, le virgolette non sono necessarie e costringono MySQL a eseguire un typecasting / conversion, quindi spreca un po ‘di tempo nella CPU. In pratica, a meno che tu non stia eseguendo un’operazione di dimensioni di Google, tale overhead di conversione sarà microscopicamente piccolo.

    Non dovresti mai mettere le virgolette sui numeri. C’è una ragione valida per questo.

    Il vero problema arriva a digitare casting. Quando inserisci i numeri tra virgolette, viene trattato come una stringa e MySQL deve convertirlo in un numero prima di poter eseguire la query. Mentre questo potrebbe richiedere un po ‘di tempo, i veri problemi iniziano a verificarsi quando MySQL non fa un buon lavoro di conversione della stringa. Ad esempio, MySQL convertirà stringhe di base come “123” all’intero 123, ma convertirà alcuni numeri più grandi, come “18015376320243459”, in virgola mobile. Poiché il punto variabile può essere arrotondato, le query possono restituire risultati incoerenti. Ulteriori informazioni su digitare casting qui . A seconda dell’hardware e del software del server, questi risultati possono variare. MySQL lo spiega.

    Se sei preoccupato per le iniezioni SQL, controlla sempre il valore e usa PHP per rimuovere tutti i numeri. È ansible utilizzare preg_replace per questo: preg_replace("/[^0-9]/", "", $string)

    Inoltre, se si scrivono le query SQL con le virgolette, non funzioneranno su database come PostgreSQL o Oracle.

    AFAIK è standard, ma è considerato una ctriggers pratica perché
    – utilizzarlo in una clausola WHERE impedirà all’ottimizzatore di utilizzare gli indici (spiegare il piano dovrebbe mostrarlo)
    – Il database deve fare ulteriori lavori per convertire la stringa in un numero
    – se stai usando questo per i numeri in virgola mobile (‘9.4’), avrai dei problemi se client e server usano impostazioni di lingua diverse (9.4 vs 9,4)

    In breve: non farlo (ma YMMV)

    Questo non è un comportamento standard.

    Per MySQL 5.5. questa è la modalità SQL predefinita

     mysql> select @@sql_mode; +------------+ | @@sql_mode | +------------+ | | +------------+ 1 row in set (0.00 sec) 

    ANSI e TRADITIONAL sono utilizzati in modo più rigoroso da Oracle e PostgreSQL. Le modalità SQL Le autorizzazioni MySQL devono essere impostate SE E SOLO SE si desidera rendere SQL più conforms ANSI. Altrimenti, non devi toccare nulla. Non l’ho mai fatto.

    Controlla questo, puoi capire meglio …

     mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347; +----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+ | 1 | SIMPLE | test_no | index | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63 | NULL | 3126240 | Using where; Using index | +----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+ 1 row in set (0.00 sec) mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347'; +----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+ | 1 | SIMPLE | test_no | const | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63 | const | 1 | Using index | +----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+ 1 row in set (0.00 sec) mysql> mysql> mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347; +----------+ | COUNT(1) | +----------+ | 1 | +----------+ 1 row in set, 1 warning (7.94 sec) mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347'; +----------+ | COUNT(1) | +----------+ | 1 | +----------+ 1 row in set (0.00 sec) 

    Non è necessario citare i numeri, ma è sempre una buona abitudine se si fa in modo coerente.

    Il problema è, diciamo che abbiamo una tabella chiamata utenti, che ha una colonna chiamata current_balance di tipo FLOAT, se si esegue questa query:

     UPDATE `users` SET `current_balance`='231608.09' WHERE `user_id`=9; 

    Il campo current_balance verrà aggiornato a 231608, perché MySQL ha fatto un arrotondamento, allo stesso modo se provi questa query:

     UPDATE `users` SET `current_balance`='231608.55' WHERE `user_id`=9; 

    Il campo current_balance verrà aggiornato a 231609