Forum » Programiranje » [MariaDB] Zakaj SQL enači "ab " z "ab" v WHERE pogoju?
[MariaDB] Zakaj SQL enači "ab " z "ab" v WHERE pogoju?
HotBurek ::
Dobro jutro.
Evo, še malo, pa bo nov dan. A nov izziv je že tu.
Setup je sledeč. Database je MariaDB (InnoDB). Tabela ima definiran stolpec "key", katerega COLLATE je utf8mb4_bin. V tem stolpcu so vnešene vrednosti dolžine od 1 do 3 ("abc", "aa", "ab", "a", "a1", "a1a" itn.). Ter, na tem stolpcu je unique index.
Zakaj pri SELECT-u, kjer je v WHERE pogoju string "ab " (a-b-presledek), vrača id za vrednost "ab"?
Zadevo sem zaenkrat pofixal tako, da v WHERE pogoju dodatno preverjam še dolžino obeh stringov (parameter ter vrednost v tabeli).
Sample test run:
Output:
Torej, zakaj v prvem primeru, kjer SQL išče string "ab " (a-b-presledek), najde match v stringu "ab"?
Test, kjer dodam string na začetku (se pravi " ab"), pa ne enači z "ab". Kar je prav.
UPDATE:
Še dve opcije za WHERE:
Vir: https://stackoverflow.com/questions/366...
Evo, še malo, pa bo nov dan. A nov izziv je že tu.
Setup je sledeč. Database je MariaDB (InnoDB). Tabela ima definiran stolpec "key", katerega COLLATE je utf8mb4_bin. V tem stolpcu so vnešene vrednosti dolžine od 1 do 3 ("abc", "aa", "ab", "a", "a1", "a1a" itn.). Ter, na tem stolpcu je unique index.
Zakaj pri SELECT-u, kjer je v WHERE pogoju string "ab " (a-b-presledek), vrača id za vrednost "ab"?
Zadevo sem zaenkrat pofixal tako, da v WHERE pogoju dodatno preverjam še dolžino obeh stringov (parameter ter vrednost v tabeli).
Sample test run:
SET @id1 = -1; SET @id2 = -1; SET @p_key = 'ab '; SELECT `id` INTO @id1 FROM `database_1`.`table_1` WHERE `key` = @p_key; SELECT `id` INTO @id2 FROM `database_1`.`table_1` WHERE `key` = @p_key AND LENGTH (@p_key) = LENGTH (`key`); SELECT @id1 AS 'id1', @id2 AS 'id2';
Output:
id1|id2| ---+---+ 97| -1|
Torej, zakaj v prvem primeru, kjer SQL išče string "ab " (a-b-presledek), najde match v stringu "ab"?
Test, kjer dodam string na začetku (se pravi " ab"), pa ne enači z "ab". Kar je prav.
UPDATE:
Še dve opcije za WHERE:
WHERE `key` = RTRIM(@p_key); WHERE BINARY `key` = @p_key;
Vir: https://stackoverflow.com/questions/366...
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
- spremenilo: HotBurek ()
kljuka13 ::
Ignoriranje presledkov pri primerjavi je namerno. Specifikacija ANSI namreč določa, da lahko primerjamo le dva niza z enako dolžino. Če je eden krajši, ga je treba dopolniti s presledki na koncu. Preden torej lahko strežnik primerja vrednosti v tvojem stolpcu `key` z vrednostjo 'ab ', jih mora narediti vse enako dolge, to pomeni, da vrednost 'ab' postane 'ab '.
Če je to v tvojem primeru zares težava, obstajajo različne rešitve.
Če je to v tvojem primeru zares težava, obstajajo različne rešitve.
- Uporaba operatorja LIKE, ki pravilno primerja nize različnih dolžin:
SELECT * FROM `table1` WHERE `key` LIKE 'ab '
- Dodatni pogoj z LENGTH oziroma DATALENGTH:
SELECT * FROM `table1` WHERE `key` = 'ab ' AND LENGTH(`key`) = LENGTH('ab ')
- Trik z dodatnim nizem:
SELECT * FROM `table1` WHERE CONCAT(`key`, '*') = CONCAT('ab ', '*')
OracleDev ::
kuall ::
fun fact: če mixaš Char(3) in varchar (3), npr spremenljivka bo eno v polju drugo, in uporabljaš like ne bo delalo prav. Ker char doda space na koncu, varchar ne, like pa potem upošteva te space. = jih ne upošteva ravno zato, da se izognemo temu bugu.
Zgodovina sprememb…
- spremenilo: kuall ()
kuall ::
In zarad podobnega razloga bi lahko ukinili null, v izogib bugom, čeprav je teoretično prav, da je null in da se space upošteva pri =.
Zgodovina sprememb…
- spremenilo: kuall ()
Utk ::
Z null ni nič narobe. Ustrelit bi pa treba tistega, ki je izumil char() z neko fiksno dolžino, ki dodaja space na koncu avtomatsko. Če je nekaj fiksne dolžine 5, naj bo 5, naj bojo tudi 4 spaci od tega zarad mene, ampak to ni enako drugemu stringu, ki ima space več ali manj. Space je čisto legit znak in ni razloga, da bi ga ignorirali ali pa dodajali kar avtomatsko. Če že je nek tip s fiksno dolžino, bi moral vržt exception, ko skušaš zapisat kaj krajšega od tega.
kuall ::
Skiši se lepo Utk, kar si spesnu ravnokar. Ampak saj se tudi teorija komunizma sliš lepo.
praksa kolega, praksa.
praksa kolega, praksa.
HotBurek ::
Polje ima tip VARCHAR(3), COLLATION je utf8mb4_bin.
Na koncu sem se odločil, da bom primerjal dolžine stringov (vhodneg parametra z vrednostjo iz table). Soldi solution.
Let's move on to the next challenge.
Na koncu sem se odločil, da bom primerjal dolžine stringov (vhodneg parametra z vrednostjo iz table). Soldi solution.
Let's move on to the next challenge.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Kako pohitrit build-anje index za autocomplete?Oddelek: Programiranje | 1084 (616) | DamijanD |
» | SQL Recursion 2.Oddelek: Programiranje | 721 (545) | korenje3 |
» | SQL vprasanje (strani: 1 2 )Oddelek: Programiranje | 8402 (5081) | BivšiUser2 |
» | PostgreSQL pomočOddelek: Programiranje | 2522 (2015) | Mato989 |
» | sql-t stored procedureOddelek: Programiranje | 1065 (932) | detroit |