2010-08-07 21 views
17

Chciałbym utworzyć zapytanie w MySQL, które ma wartość opcjonalną. Po określeniu wartości zapytanie jest filtrowane według tej wartości, gdy wartość nie jest zwracana. Oto pomysł:MySQL gdzie klauzula jest równa wszystkim (SELECT * WHERE col = ANY_VALUE)

public function doQuery($item = 'ANY_VALUE') { 
    $query = "SELECT * FROM table WHERE item = ?"; 
    db->fetchAll($query,array($item)) 
    ... 
} 

doQuery(); // Returns everything 
doQuery($item='item1'); // Returns only rows where item = 'item1' 

Czy istnieje prosty sposób to zrobić bez tworzenia dwóch ciągów zapytań w zależności od wartości $ sprzęcie?

+0

Mogłaby sformułować również przy użyciu PHP. –

Odpowiedz

17

O ile mi wiadomo, nie ma takiego "jakiegokolwiek" symbolu zastępczego.

Jeśli można użyć podobnych, można zrobić

SELECT * FROM table WHERE item LIKE '%' 

jeśli można dodać warunek, można unieważnić klauzuli item takiego:

SELECT * FROM table WHERE item = ? OR 1=1 

(nie będzie pracować w na przykład, ponieważ przekazujesz "element" jako parametr)

To są wszystkie opcje, które mogę zobaczyć - najprawdopodobniej najłatwiej jest pracować z dwoma zapytaniami, usuwając WHERE w drugiej klauzuli.

To prawdopodobnie zadziała, ale nie jestem pewien, czy to dobry pomysł z punktu widzenia bazy danych.

public function doQuery($item = 'ANY_VALUE') { 
    $query = "SELECT * FROM table WHERE item = ? OR 1 = ?"; 
    db->fetchAll($query,array($item, ($item == 'ANY_VALUE' ? 1 : 0)) 
    ... 
} 
+0

Interesujące pomysły. Pomysł na klauzulę LIKE może zadziałać, ale myślę, że to zaszkodzi wydajności. Dołączanie innej klauzuli where wymagałoby manipulowania ciągiem zapytania, którego chciałem uniknąć. Gdybym chciał przejść tę trasę, mógłbym dodać "item =?" bezpośrednio do ciągu zapytania ... – user27478

+2

Rozszerzenie drugiego przykładu: SELECT * FROM table WHERE item =? OR 1 =? Umieść 0 w drugim parametrze, jeśli chcesz mieć określone wiersze, lub 1, jeśli chcesz wszystkie – Mchl

+0

I * myślę, że MySQL spowoduje zwarcie instrukcji 'LIKE '%'' do '1 = 1' ... Wypróbuj (i wątpię, że to zaszkodzi wydajności, nawet jeśli nie jest to zwarcie, ponieważ i tak potrzebujesz pełnego skanowania tabeli ... – ircmaxell

-1

Nie ma powodu, aby robić to za pomocą jednego zapytania. Uruchomienie zapytania bez klauzuli WHERE powoduje, że jest jasne, że chcesz zwrócić wszystkie wiersze. Uruchomienie go z klauzulą ​​WHERE powoduje, że jest jasne, że chcesz filtrować wiersze.

+1

Faktycznie uruchomione zapytanie jest znacznie bardziej skomplikowane niż przykład, który podałem. Zgodnie z zasadą DRY nie chcę utrzymywać dwóch kopii tego, co jest zasadniczo tym samym zapytaniem (plus lub minus jedna klauzula where). – user27478

+1

Jeśli dobrze Cię rozumiem, nadal możesz skonstruować zapytanie w jednym miejscu, rozgałęziając się tylko na podstawie tego, czy parametr $ item ma wartość. Nie uważa, że ​​naruszenie DRY. – mwittrock

+0

@gerdemb, jeśli jedno zapytanie ma warunek WHERE, a drugie nie, w żadnym przypadku nie można uznać ich za "zasadniczo to samo zapytanie".Błędem jest założenie, że ponieważ tekst dwóch różnych zapytań jest podobny, semantyka obu zapytań jest podobna. –

3

Lepszym sposobem na zrobienie tego jest najpierw wygenerowanie zapytania sql z parametru, który trzeba zawracać, a następnie wykonać.

function doQuery($params) { 
    $query = 'SELECT * FROM mytable '; 
    if (is_array($params) // or whatever your condition) { 
     $query .= 'WHERE item = ' . $params[0]; 
    } 
    $query .= ' ;'; 

    // execute generated query 
    execute($query); 
}