tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

WHERE %and vs NULL (MySQL)

před 11 lety

phx
Člen | 652

Zdravim…
Narazil jsem na problem. Kdyz do Dibi poslu napr SQL:

$array = array('name'=>null);
dibi::query('SELECT * FROM [table] WHERE %and', $array);

tak mi to vrati SQL:

SELECT * FROM `table` WHERE `name`=NULL

Coz nic nenajde protoze spravne to je:

SELECT * FROM `table` WHERE `name` IS NULL

Reseni je jedine v zasahu do dibi nebo sestavovat dotaz rucne.

Dale pokud $array = array() SQL je:

SELECT * FROM `table` WHERE `name`

Osobne bych cekal, ze to bude:

SELECT * FROM `table` WHERE 1

Ale to je drobnost. To prvni me trapi hodne.

Dale me napada, ze by mozna stalo za to realizovat podporu pro IN (…) a LIKE.
Napriklad takto:

$array = array(
    'id%in'=>array(1, 2, 3)
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `id` IN (1, 2, 3)

$array = array(
    'name%like'=>'phx%'
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `name` LIKE 'phx%'

Editoval phx (18. 8. 2008 13:20)

před 11 lety

phx
Člen | 652

Zadna reakce?

před 11 lety

David Grudl
Nette Core | 6806

phx napsal(a):

SELECT * FROM `table` WHERE `name`=NULL

opraveno.

Osobne bych cekal, ze to bude:

SELECT * FROM `table` WHERE 1

Opraveno.

Dale me napada, ze by mozna stalo za to realizovat podporu pro IN (…) a LIKE.
Napriklad takto:

$array = array(
  'id%in'=>array(1, 2, 3)
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `id` IN (1, 2, 3)

$array = array(
  'name%like'=>'phx%'
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `name` LIKE 'phx%'

To jsou výborné nápady, ale šel bych ještě o kousek dál: prostě rozšířit klíč o operátor. Otázkou je, jak ho oddělit – co třeba mezerou? Prostě 'klic%modifikator operator'. Takže třeba

$array = array(
    'id%l IN'=>array(1, 2, 3) // %l je modifikátor pro list, IN je operátor
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `id` IN (1, 2, 3)

$array = array(
    'name% LIKE'=>'phx%' // modifikátor vynecháme, jen operátor LIKE
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `name` LIKE 'phx%'

před 11 lety

phx
Člen | 652

Hezky, ale nejak me nenapada vyhoda (vyuziti) oddeleni modifikatoru od klice.

před 11 lety

David Grudl
Nette Core | 6806

Jak to myslíš?

před 11 lety

phx
Člen | 652

Proste nenapada me k cemu by to bylo dobre: 'klic%modifikator operator'

před 11 lety

David Grudl
Nette Core | 6806

před 11 lety

phx
Člen | 652

Nevim, mozna SQL neznam dobre ztak jak jsem si myslel, ale u IN jsou vzdy data v zavorkach oddelene carkou a ohledne LIKE nevidim vyhodu toho, ze na to mohu pouzit nejaky modifikator. Osobne by mi prislo logictejsi:
id%inname%like

Chci tim take rict, ze mohou vznikat konstrukce jako id%a IN coz si nedovedu predstavit v SQL.

před 11 lety

David Grudl
Nette Core | 6806

Ono jde spíš o to, že těch operátorů existuje hodně, navíc kromě IN a LIKE může být třeba NOT IN, NOT LIKE atd. Účelem modifikátoru je říct, jak hodnotu vložit do SQL, nikoliv co se s ní bude provádět, a tak by to asi mělo zůstat.

Pro začátek rozšířím %and a %or tak, aby generovalo

$array = array(
    'id%l' => array(1, 2, 3)
);
dibi::query('SELECT * FROM [table] WHERE %and', $array);
// SELECT * FROM `table` WHERE `id` IN (1, 2, 3)

tedy zachovám jim vlastnost porovnávání, tedy přes operátory =, IS nebo IN. Implementace jiných operátorů bude vyžadovat trošku hlubší analýzu.

před 11 lety

PetrP
Člen | 587

Tohle ještě není funkční nebo dělám něco špatně?

před 11 lety

phx
Člen | 652

Potreboval bych v poli definovat nejak NOT.

SELECT COUNT(*) FROM tabulka WHERE neco <> 10

SELECT COUNT(*) FROM tabulka WHERE neco NOT IN (10, 20, 30)

Predstava:

$where = array(
    '~neco'=>10,
);

// nebo

$where = array(
    '~neco'=>array(10, 20, 30)',
);

Nebo to nejak jde?

před 11 lety

phx
Člen | 652

Pohnul se vyvoj nejak? NOT by se mi hodilo…

Pokud by jsi chtel pomoci s vyvojem staci rict.

před 11 lety

blacksun
Člen | 181

K tomuto bych měl dotaz, jestli se dá nějak pracovat s polem podmínek, kde nejde o rovnost, ale větší menší apod., např. datum > 2008–10–10 AND datum < 2009–01–01.

před 11 lety

David Grudl
Nette Core | 6806

phx napsal(a):

Pohnul se vyvoj nejak? NOT by se mi hodilo…

Pokud by jsi chtel pomoci s vyvojem staci rict.

No… 5.9.2008 jsi mi to vehementně rozmlouval :-)

před 11 lety

phx
Člen | 652

To jsme si asi neporozumneli. Ja jsem chtel naznacit, ze by mohly vznikat nesmyslne konstrukce typu

SELECT * FROM tabulka WHERE sloupecek IN (klic='hodnota', klic2='hodnota2')

Osobne jsem to zatim resil pres DibiFluent, ale i tam to neni idealni.

před 11 lety

David Grudl
Nette Core | 6806

Nene, o takové konstrukce vůbec nešlo, šlo o ty NOT IN, LIKE, <, > atd, viz příklad výše. Např:

$where = array(
        'neco% NOT IN'=>array(10, 20, 30)',
);

Ale jak říkám, nechal jsem si to rozmluvit :-)) a dnes se k té koncepci vracet nechci, už bych šel jinou cestou. Například:

$items = array(10, 20, 30);
$where = array(
        array('[neco] NOT IN (%i)', $items),
);

před 11 lety

David Grudl
Nette Core | 6806

blacksun napsal(a):

K tomuto bych měl dotaz, jestli se dá nějak pracovat s polem podmínek, kde nejde o rovnost, ale větší menší apod., např. datum > 2008–10–10 AND datum < 2009–01–01.

Viz předchozí post, podpora by mohla vypadat třeba takto:

$where = array();
$where[] = array('datum > %d', '2008-10-10');
$where[] = array('datum < %d', '2009-01-01');
$where[] = ...;
dibi::query("SELECT * FROM posts WHERE %and", $where);

před 11 lety

phx
Člen | 652

Nad necim podobnym jsem take uvazoval, a chtel jsem si to rucne implementovat za pomoci %ex, ale nakonec jsem sel jinudy (DibiFluent).

Soucasne dibi tot nezvlada, ale bylo by to fajn, kdyby to umelo. V podstate staci udelat vyjimku aby to ciselne klice v poli vyhodnocovalo za pomoci %ex a nebralo to klic jako nazev sloupecku.

Pokud se v tom budes vrtat tak i tato uprava by mohla byt hezka ne?

$where = array(
    '~neco'=>10,
);

před 11 lety

David Grudl
Nette Core | 6806

%ex by šlo taky (přidám), v poslední revizi to už dnes lze přes %sql a číselné klíče v poli se tak vyhodnocují. Vyzkoušej.

Přidávat '~neco' nechci, je to hezké, ale někdo může používat tento znak v názvu sloupce.

před 11 lety

phx
Člen | 652

SUPR SUPR SUPR:)

Vpodstate to vyresilo vsechny problemy v tomto vlaknu;) DIKY

před 11 lety

krajaac
Člen | 45

Mam jeste jeden dotaz,
jde v dibi spojovat v kauzuli WHERE podminky pomoci AND a OR zaroven?

Potreboval bych zkonstruovat neco v tomto stylu:
SELECT * FROM users WHERE sex = 'female' AND (chest >= 90 OR height >= 170)

vite nekdo jak na to? :)

Editoval krajaac (15. 1. 2009 20:04)

před 11 lety

phx
Člen | 652

Doporucil bych DibiFluent.

Jinak v array by to take mohlo jit nejak takto:

// pak vlozit jako parametr za %and
$where = array(
    'sex'=>'female',
    '(chest >= 90 OR height >= 170)'
);

Pisu to bez otestovani z hlavy. Snad to bude OK.

před 11 lety

krajaac
Člen | 45

phx napsal(a):

Doporucil bych DibiFluent.

Jinak v array by to take mohlo jit nejak takto:

// pak vlozit jako parametr za %and
$where = array(
  'sex'=>'female',
  '(chest >= 90 OR height >= 170)'
);

Pisu to bez otestovani z hlavy. Snad to bude OK.

Diky za radu, jeste jsem to netestoval. Uvedomil jsem si, ze do dotazu cpat OR vubec neporebuju :D

Nicmene jsem zkousel zapis ve stylu:

<?php
$dibifluent
    ->select...->from...
    ->where(array('sex' => 'female'))
    ->where('%or', array('chest >= %i' => 90, 'chest >= %i' => 170) )
    ->limit...
?>

Ale nefungoval – vsechny prvky spojil ANDem.

před 11 lety

David Grudl
Nette Core | 6806

Ve výrazu

->where('%or', array('chest >= %i' => 90, 'chest >= %i' => 170) )

se chápe 'chest >= %i' jako název klíče, tohle fungovat nebude.

před 11 lety

David Grudl
Nette Core | 6806

David Grudl napsal(a):

Varianta s %ex také funguje. Příklady použití:

// ekvivalentní zápisy:
$pocet = 10;
$where[] = array('pocet > %i', $pocet);

$where['pocet%ex'] = array('> %i', $pocet);

Uvažuju nad tím, že to nebyl dobrý krok, lepší bude ponechat jen $where[] = array('pocet > %i', $pocet) a variantu $where['pocet%ex'] = array('> %i', $pocet); udělat ekvivalentní s %sql.