В состав операторов SELECT, UPDATE и DELETE в качестве важной части входит условие WHERE. Оно определяет активный набор (active set) -множество строк, которое возвращается запросом SELECT или на которое воздействует оператор UPDATE или DELETE.
Предложение WHERE строится из условий, соединенных логическими операциями AND (и), OR (или) и NOT (не). Эти условия обычно имеют форму сравнений, например:
Приведенный блок удалит все строки таблицы classes, для которых заданное условие истинно (т.е. значение поля department равно 'CS'). При проведении сравнений следует обращать внимание на несколько моментов, в том числе на имена переменных и на способ сравнения символов.
Имена переменных
Представим себе, что в предыдущем блоке имя переменной изменено с v_Department на department:
Это простое изменение оказывает значительное влияние на результаты выполнения оператора: из таблицы classes будут удалены все строки, а не только те, у которых значение факультета равно 'CS'! Все дело в способе осуществления синтаксического анализа идентификаторов SQL- оператора. Когда PL/SQL встречает условие вида
эти выражения вначале проверяются на соответствие столбцам таблицы, над которой выполняется операция. Затем проверяется наличие в блоке PL/SQL переменных. PL/SQL безразличен к регистру символов, поэтому в нашем блоке как department, так и Department ассоциируются со столбцом таблицы classes, а не с переменной. Указанное условие истинно для каждой строки таблицы, поэтому все строки будут удалены.
Если для блока создана, метка, то для переменной и столбца можно использовать одинаковые имена, но в этом случае надо указать метку при ссылке на переменную. Ниже приведен блок, выполнение которого дает нужный эффект, т.е. удаляются только те строки, в которых department = 'CS'.
Такой способ допустим, использование одного и того же имени
для переменной PL/SQL и для столбца таблицы считается плохим стилем
программирования (см. главу 3). Сравнение символов
В Oracle при сравнении двух символьных значений могут использоваться два метода: сравнение с дополнением пробелами и сравнение без дополнения пробелами. Эти два метода различаются способом сравнения
строк символов с разной длиной. Предположим, что имеются две строки
символов - stringl и string2. При сравнении с дополнением пробелами применяется следующий алгоритм:
Если длины строк различны, то сначала более короткое значение дополняется пробелами, чтобы строки имели одинаковую длину.
Строки сравниваются посимвольно, начиная слева. Допустим, что сравниваются charl — символ из stringl и char2 — символ из string2.
Если ASCII (charl) < ASCII(char2), то stringl < string2. Если ASCII(char1)>ASCII(char2),Tostringl>string2.EcTHASCII(char1) = ASCII(char2), то берутся следующие символы stringl и string2.
Если достигнут конец каждой из строк, то строки равны.
При использовании данного метода следующие условия будут истинными:
Алгоритм сравнения строк символов без дополнения пробелами выглядит несколько иначе:
Строки сравниваются посимвольно, начиная слева. Допустим, что сравниваются charl — символ из stringl и char2 — символ из string2.
Если ASCII(charl) < ASCII(char2), то stringl < string2. Если ASCII(charl) >ASCII(char2), то stringl > string2. ЕслиАЗСП(сПаП) = ASCII(char2), то берутся следующие символы stringl и string2.
Если конец stringl достигается раньше конца string2, то stringl < string2. Если конец string2 достигается раньше конца stringl, то stringl > string2.
Если достигнут конец каждой из строк, то строки равны.
Так когда же какой метод следует использовать? В PL/SQL метод сравнения с дополнением пробелами применяется только в том случае, когда оба сравниваемых значения имеют фиксированную длину. Если же одно из значений имеет переменную длину, то применяется сравнение без дополнения пробелами. Данные типа CHAR имеют фиксированную длину, а данные типа VARCHAR2 — переменную. Считается, что символьные литералы (заключенные в одиночные кавычки) всегда имеют фиксированную длину.
Если оператор не оказывает воздействия на нужные строки, проверьте типы данных, используемые в условии WHERE. Ниже приводится блок, в результате выполнения которого ни одна строка удалена не будет, так как переменная v_Department имеет тип VARCHAR2, а не CHAR.
Столбец department таблицы classes имеет тип CHAR. Поэтому для всех компьютерных групп значение department будет равно 'CS' (обратите внимание на конечный пробел). Значение переменной v_Department равно 'CS' (конечный пробел отсутствует), и она имеет тип данных переменной длины, поэтому оператор DELETE не оказывает никакого влияния на строки.
Для получения нужного эффекта от условия WHERE следите за тем,
чтобы переменные в блоке PL/SQL имели те же типы, что и столбцы
базы данных, с которыми сравниваются переменные. Это можно гарантировать, если использовать атрибут %TYPE.
< Предыдущая | Следующая > |
---|