Создание долгого запроса и имеет, многие из если операторы - являются там более изящным путем?

Я должен создать запрос на основе определенных условий. Существует ли лучший способ сделать его, чем способ, которым я сделал ниже? Это хорошо работает, но я вижу, что он выходит из-под контроля справедливо быстро, если было больше условий, так как я проверяю, соблюдали ли какие-либо предыдущие условия каждый раз, когда я проверяю новый.

    $sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime";

    if (!empty($day) || !empty($time) || !empty($sportID)) {

        $sql .= " WHERE";

        if (!empty($day)) {
            $sql .= " fldDay='$day'";
        }

        if (!empty($time)) {
            if (!empty($day)) {
                $sql .= " AND";
            }
            $sql .= " fldTime='$time'";
        }

        if (!empty($sportID)) {
            if (!empty($day) || !empty($time)) {
                $sql .= " AND";
            }
            $sql .= " fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
        }

    }
7
задан birderic 12 August 2010 в 18:52
поделиться

8 ответов

Я бы использовал старый «WHERE 1 = 1» трюк; добавьте это как первое условие, а затем вы можете принять условие «И» для каждого следующего оператора.

6
ответ дан 6 December 2019 в 21:08
поделиться
$sql = "SELECT DISTINCT fkRespondentID FROM tblRespondentDayTime WHERE 1=1";

if (!empty($day))
    $sql .= "AND fldDay='$day'";

if (!empty($time)) {
    $sql .= "AND fldTime='$time'";

if (!empty($sportID))
    $sql .= "AND fkRespondentID IN (SELECT fkRespondentID FROM tblRespondentSport WHERE fkSportID='$sportID')";
4
ответ дан 6 December 2019 в 21:08
поделиться

Создайте список / массив условий, в котором каждое условие является необязательным (т.е. если условие действительно, поместите его в список).

Если этот список> 0, добавьте «где», а затем добавьте список, соединенный «и».

1
ответ дан 6 December 2019 в 21:08
поделиться

Вместо того, чтобы выполнять такие проверки, как if (! Empty ($ day) ||! Empty ($ time)) , вы можете создать $ whereClause переменную и проверьте ее следующим образом:

$sql = "SELECT DISTINCT fkRespondentID 
        FROM tblRespondentDayTime";

$whereClause = '';

// fldDay
if (!empty($day)) {
    $whereClause .= " fldDay='$day'";
}

// fldTime
if (!empty($time)) {
    if (!empty($whereClause)) {
        $whereClause .= ' AND ';
    }
    $whereClause .= " fldTime='$time'";
}

// fkRespondentID
if (!empty($sportID)) {
    if (!empty($whereClause)) {
        $whereClause .= ' AND ';
    }
    $whereClause .= " fkRespondentID IN (SELECT fkRespondentID 
                                         FROM tblRespondentSport 
                                         WHERE fkSportID='$sportID')";
}

if (!empty($whereClause)) {
    $whereClause = ' WHERE '.$whereClause;
}

$sql .= $whereClause;

Это также сработает, если вам нужно, скажем, изменить некоторые на ИЛИ (1 = 1 трюк в этом случае не сработает и даже может оказаться довольно опасным ).

1
ответ дан 6 December 2019 в 21:08
поделиться

вы можете попробовать поместить свои переменные в массив и иметь логическое значение, которое сообщает, нужно ли вам добавить «И» перед следующей фразой. Это сократит ваши управляющие операторы до foreach и вложенного if.

0
ответ дан 6 December 2019 в 21:08
поделиться

Вот мое решение:

$sql = "SELECT * FROM table";
$conditions = array(
  'fldDay' => $day,
  'fldTime' => $time,
);

if (count(array_filter($conditions))) {
  $sql .= ' WHERE ';
  $sql .= implode(' AND ', array_map(function($field, $value) {
    return $field . '=\'' . pg_escape_string($value) . '\'';
  }, array_keys($conditions), $conditions));
}

Обратите внимание, что из-за закрытий это не будет работать ниже PHP 5.3. Если вы используете старый PHP, сделайте закрытие отдельной функцией или замените его на foreach .

0
ответ дан 6 December 2019 в 21:08
поделиться

К сожалению, создание динамического SQL - утомительное занятие, и даже если вы можете изменить несколько вещей в своей логике (которая на самом деле выглядит относительно чистой), это все равно будет некрасиво.

К счастью, Объектно-реляционное отображение существует. Я не слишком знаком с PHP, но Perl имеет несколько модулей CPAN, таких как SQL :: Abstract, которые позволят вам создавать довольно сложные операторы SQL с использованием базовых структур данных.

0
ответ дан 6 December 2019 в 21:08
поделиться

Если вы используете хранимые процедуры, вы можете сделать что-то вроде этого:

CREATE PROCEDURE `FindRespondents` (
    IN `_day` varchar(255),
    ...
)
BEGIN
    SELECT DISTINCT fkRespondentID 
    FROM tblRespondentDayTime
    WHERE (_day Is Null OR fldDay = _day)
        AND ...
END;
|

Передача null для _day означает, что любой fldDay допустим. Любое другое значение для _day , и оно должно быть сопоставлено. Я предположил, что fldDay - это текст, но, конечно, вы можете ввести здесь все правильно.

Я знаю, что некоторые люди не поклонники хранимых процедур, но может быть удобно инкапсулировать логику запросов таким образом.

0
ответ дан 6 December 2019 в 21:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: