Главная страница
Навигация по странице:

  • UPDATE

  • Оператор DELETE Оператор DELETE

  • IDENTITY

  • DELETE

  • RESTART IDENTIT

  • AUTO_INCREMENT

  • Готовимся ко второму этапу тестирования

  • Функция DATEADD Функция DATEADD

  • Datepart Допустимые сокращения Year — год yy, yyyy Quarter — квартал qq, q Month — месяц mm, m Dayofyear — день года

  • CURRENT_TIMESTAMP

  • MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR SECOND_MICROSECOND

  • DAY_HOUR YEAR_MONTH

  • лекция. Учебник по sql если вы хотите узнать, что такое sql этот сайт для вас


    Скачать 7.88 Mb.
    НазваниеУчебник по sql если вы хотите узнать, что такое sql этот сайт для вас
    Анкорлекция
    Дата21.12.2022
    Размер7.88 Mb.
    Формат файлаpdf
    Имя файлаMoiseenko_SQL.pdf
    ТипУчебник
    #857633
    страница24 из 47
    1   ...   20   21   22   23   24   25   26   27   ...   47
    CAST (пункт 5.9).
    Если требуется изменять данные в зависимости от содержимого некоторого столбца, можно воспользоваться выражением CASE (пункт 5.9) Если, скажем, нужно поставить жесткие диски объемом 20 Гбайт на портативные компьютеры с памятью менее 128 Мбайт и 40 гигабайтные — на остальные портативные компьютеры, то можно написать такой запрос:
    1.
    UPDATE
    Laptop
    2.
    SET
    hd =
    CASE
    3.
    WHEN
    ram <
    128 4.
    THEN
    20 5.
    ELSE
    40 6.
    END
    ;
    Для вычисления значений столбцов допускается также использование подзапросов. Например, требуется укомплектовать все портативные компьютеры самыми быстрыми процессорами из имеющихся в наличии.
    Тогда можно написать:
    1.
    UPDATE
    Laptop
    2.
    SET
    speed =
    (
    SELECT
    MAX
    (
    speed
    )
    3.
    FROM
    Laptop
    4.
    )
    ;
    Необходимо сказать несколько слов об автоинкрементируемых столбцах.
    Если столбец code в таблице Laptop определен как IDENTITY(1,1), то следующий оператор

    1.
    UPDATE
    Laptop
    2.
    SET
    code =
    5 3.
    WHERE
    code =
    4
    ; не будет выполнен, так как автоикрементируемое поле не допускает обновления, и мы получим соответствующее сообщение об ошибке. Чтобы выполнить все же эту задачу, можно поступить следующим образом. Сначала вставить нужную строку, используя SET IDENTITY_INSERT, после чего удалить старую строку:
    1.
    SET
    IDENTITY_INSERT Laptop_ID
    ON
    ;
    2.
    INSERT
    INTO
    Laptop_ID
    (
    code, model, speed, ram, hd, price, screen
    )
    3.
    SELECT
    5
    , model, speed, ram, hd, price, screen
    4.
    FROM
    Laptop_ID
    WHERE
    code =
    4
    ;
    5.
    DELETE
    FROM
    Laptop_ID
    6.
    WHERE
    code =
    4
    ;
    Разумеется, другой строки со значением code = 5 в таблице быть не должно.
    В
    Transact-SQL
    оператор UPDATE расширяет стандарт за счет применения необязательного предложения FROM. В этом предложении специфицируется таблица, обеспечивающая критерий для операции обновления.
    Дополнительную гибкость здесь дают операции соединения таблиц.
    Пример 6.2.1.
    Пусть требуется указать «No PC» (нет ПК) в столбце type для
    тех моделей ПК из таблицы Product, для которых нет
    соответствующих строк в таблице PC. Решение посредством
    соединения таблиц можно записать так
    1.
    UPDATE
    Product
    2.
    SET
    type =
    'No PC'
    3.
    FROM
    Product pr
    LEFT
    JOIN
    4. PC
    ON
    pr.model=PC.model
    5.
    WHERE
    type =
    'pc'
    AND
    6. PC.model
    IS
    NULL
    ;

    Здесь применяется внешнее соединение, в результате чего столбец PC.model для моделей ПК, отсутствующих в таблице PC, будет содержать NULL- значение, что и используется для идентификации подлежащих обновлению строк. Естественно, эта задача имеет решение и в «стандартном» исполнении:
    1.
    UPDATE
    Product
    2.
    SET
    type =
    'No PC'
    3.
    WHERE
    type =
    'pc'
    AND
    4. model
    NOT
    IN
    (
    SELECT
    model
    5.
    FROM
    PC
    6.
    )
    ;
    Оператор
    DELETE
    Оператор DELETE удаляет строки из временных или постоянных базовых таблиц, представлений или курсоров, причем в двух последних случаях действие оператора распространяется на те базовые таблицы, из которых извлекались данные в эти представления или курсоры.
    Оператор удаления имеет простой синтаксис:
    1.
    DELETE
    FROM
    <имя таблицы >
    2.
    [
    WHERE
    <предикат>
    ]
    ;
    Если предложение WHERE отсутствует, удаляются все строки из таблицы или представления (представление должно быть обновляемым). Более быстро эту операцию (удаление всех строк из таблицы) можно в
    Transact-SQL
    также выполнить с помощью команды
    1.
    TRUNCATE
    TABLE
    <имя таблицы>
    Однако есть ряд особенностей в реализации команды TRUNCATE TABLE, которые следует иметь в виду:


    не журнализируется удаление отдельных строк таблицы; в журнал записывается только освобождение страниц, которые были заняты данными таблицы;

    не отрабатывают триггеры, в частности, триггер на удаление;

    команда неприменима, если на данную таблицу имеется ссылка по внешнему ключу, и даже если внешний ключ имеет опцию каскадного удаления.

    значение счетчика (IDENTITY) сбрасывается в начальное значение.
    Пример 6.3.1
    Требуется удалить из таблицы Laptop все портативные
    компьютеры с размером экрана менее 12 дюймов.
    1.
    DELETE
    FROM
    Laptop
    2.
    WHERE
    screen <
    12
    ;
    Все блокноты можно удалить с помощью оператора
    1.
    DELETE
    FROM
    Laptop; или
    1.
    TRUNCATE
    TABLE
    Laptop;
    Transact-SQL расширяет синтаксис оператора DELETE, вводя дополнительное предложение FROM:
    1.
    FROM
    <источник табличного типа>
    При помощи источника табличного типа можно конкретизировать данные, удаляемые из таблицы в первом предложении FROM.
    При помощи этого предложения можно выполнять соединения таблиц, что логически заменяет использование подзапросов в предложении WHERE для идентификации удаляемых строк. Поясним сказанное на примере.
    Пример 6.3.2
    Пусть требуется удалить те модели ПК из таблицы Product, для
    которых нет соответствующих строк в таблице PC.
    Используя стандартный синтаксис, эту задачу можно решить следующим запросом:

    1.
    DELETE
    FROM
    Product
    2.
    WHERE
    type =
    'pc'
    AND
    3. model
    NOT
    IN
    (
    SELECT
    model
    4.
    FROM
    PC
    5.
    )
    ;
    Заметим, что предикат type = 'pc' необходим здесь, чтобы не были удалены также модели принтеров и портативных компьютеров.
    Эту же задачу можно решить с помощью дополнительного предложения FROM следующим образом:
    1.
    DELETE
    FROM
    Product
    2.
    FROM
    Product pr
    LEFT
    JOIN
    3. PC
    ON
    pr.model = PC.model
    4.
    WHERE
    type =
    'pc'
    AND
    5. PC.model
    IS
    NULL
    ;
    Здесь применяется внешнее соединение, в результате чего столбец PC.model для моделей ПК, отсутствующих в таблице PC, будет содержать NULL- значение, что и используется для идентификации подлежащих удалению строк.
    Оператор TRUNCATE TABLE
    Как отмечалось выше, при выполнении этой команды значение счетчика
    (IDENTITY) сбрасывается в начальное значение. Давайте проверим это утверждение в MS SQL Server. Для начала создадим таблицу с автоинкрементируемым столбцом, и добавим в нее три строки.
    1.
    CREATE
    TABLE
    Truncate_test
    (
    id INT IDENTITY
    (
    5
    ,
    5
    )
    PRIMARY
    KEY
    , val INT
    )
    ;
    2. GO
    3.
    INSERT
    INTO
    Truncate_test
    (
    val
    )
    4.
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ;
    5.
    SELECT
    *
    FROM
    Truncate_test;
    6. GO
    Начальным значением счетчика является 5, приращение счетчика выполняется также с шагом
    5.
    В результате получим:

    id
    val
    5
    1
    10 2
    15 3
    Теперь удалим строки с помощью оператора DELETE, после чего снова вставим те же строки в таблицу.
    1.
    DELETE
    FROM
    Truncate_test;
    2. GO
    3.
    INSERT
    INTO
    Truncate_test
    (
    val
    )
    4.
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ;
    5.
    SELECT
    *
    FROM
    Truncate_test;
    6. GO
    id
    val
    20
    1
    25 2
    30 3
    Как видно из результата, состояние счетчика не было сброшено, и приращение продолжилось с последнего значения (15), в отличие от использования оператора TRUNCATE TABLE:
    1.
    TRUNCATE
    TABLE
    Truncate_test;
    2. GO
    3.
    INSERT
    INTO
    Truncate_test
    (
    val
    )
    4.
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ;
    5.
    SELECT
    *
    FROM
    Truncate_test;
    6. GO

    id
    val
    5
    1
    10
    2
    15 3
    В то же время Стандарт предполагает несколько иное поведение.
    Стандартный синтаксис имеет вид
    1.
    TRUNCATE
    TABLE
    < имя таблицы >
    [{
    CONTINUE IDENTITY
    }
    |
    {
    RESTART IDENTITY
    }]
    т.е. значение счетчика может быть сброшено (опция RESTART IDENTITY) или продолжено (опция CONTINUE IDENTITY). И, кстати, значением по умолчанию является как раз CONTINUE IDENTITY, что эквивалентно поведению при использованию оператора DELETE (без предложения
    WHERE).
    Оператор TRUNCATE TABLE неприменим, если на таблицу имеется ссылка по внешнему ключу. Это стандартное поведение имеет место в SQL Server.
    Если создать, например, такую ссылающуюся таблицу, которая даже не будет содержать данных
    1.
    CREATE
    TABLE
    Trun_Ref
    (
    id INT
    REFERENCES
    Truncate_test
    )
    ; оператор TRUNCATE TABLE приведет к следующей ошибке:
    Cannot truncate table 'Truncate_test' because it is being referenced by a
    FOREIGN KEY constraint.
    (Невозможно усечь таблицу 'Truncate_test', поскольку на нее ссылается ограничение FOREIGN KEY) .

    Теперь проверим, насколько близки к стандарту другие реализации.
    PostgreSQL
    1. Поддерживаются опции CONTINUE IDENTITY и RESTART
    IDENTITY, при этом опция CONTINUE IDENTITY принимается по умолчанию.
    2. Можно удалить одним оператором строки из нескольких таблиц, перечислив их через запятую.
    3. Допускаются каскадные операции, т.е. усечение связанных таблиц:
    1.
    TRUNCATE
    TABLE
    Truncate_test RESTART IDENTITY CASCADE;
    Причем происходит именно усечение, а не удаление связанных строк. Т.е. если вставить в ссылающуюся таблицу среди прочих строку с NULL- значением во внешнем ключе
    1.
    INSERT
    INTO
    Trun_Ref
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    NULL
    )
    ; то она также будет удалена наряду с остальными.
    Oracle
    1. В Oracle нет функции для автоинкремента, которую можно указать в определении столбца. Однако поведение автоинкремента можно сымитировать с помощью последовательности (SEQUENCE).
    Например, подобную ранее рассмотренной таблицу Truncate_test в
    Oracle можно создать следующим образом:
    1.
    CREATE
    SEQUENCE u_seq
    2. START
    WITH
    5 3. INCREMENT
    BY
    5
    ;
    4. /
    5.
    CREATE
    TABLE
    Truncate_test
    (
    id INT
    PRIMARY
    KEY
    , val int
    )
    ;
    6. /
    7.
    INSERT
    INTO
    Truncate_test
    (
    id, val
    )

    8.
    VALUES
    (
    u_seq.
    NEXTVAL
    ,
    1
    )
    ;
    9.
    INSERT
    INTO
    Truncate_test
    (
    id, val
    )
    10.
    VALUES
    (
    u_seq.
    NEXTVAL
    ,
    2
    )
    ;
    11.
    INSERT
    INTO
    Truncate_test
    (
    id, val
    )
    12.
    VALUES
    (
    u_seq.
    NEXTVAL
    ,
    3
    )
    ;
    2. При выполнении оператора TRUNCATE TABLE Truncate_test состояние счетчика (последовательности) не сбрасывается, и нумерация будет продолжена.
    3. Каскадные операции не допускаются, т.е. оператор неприменим, если на таблицу есть ссылка по внешнему ключу.
    MySQL
    1. Не поддерживаются опции CONTINUE IDENTITY и RESTART
    IDENTITY, при этом состояние счетчика (AUTO_INCREMENT) сбрасывается.
    2. Допускаются каскадные операции по аналогичии с оператором
    DELETE, т.е. если внешний ключ имеет опцию ON DELETE
    CASCADE, то удаляются только связанные записи. Это значит, что строки с NULL-значением внешнего ключа остаются после выполнения оператора
    1.
    TRUNCATE
    TABLE
    Truncate_test;
    Готовимся ко
    второму
    этапу
    тестирования
    Задачи, рассмотренные нами ранее в главах 3–4, составляют первый, или обучающий, этап тестирования на сайте. Эти относительно простые задачи, для решения которых, как правило, не требуется знания особенностей реализации. Это означает, что решение практически любой из них
    можно получить, используя конструкции языка SQL, оформленные стандартом SQL-92.
    На втором этапе предлагаются более сложные задачи, для решения которых уже не обойтись без знаний конкретной реализации, например, функций работы со строками и значениями типа даты/времени.
    Задачи этого этапа не рассматриваются в книге, так как по результатам их решения на сайте можно получить сертификат. Тем не менее, мы считаем необходимым познакомить читателя со специфическими особенностями
    SQL
    Server, а также некоторыми алгоритмическими приемами, которые могут применяться для решения как задач на сайте, так и задач, часто возникающих на практике.
    Функции Transact-
    SQL для работы со строками и данными типа даты/времени
    Стандарт SQL-92 специфицирует незначительное число функций для работы со строковыми значениями и значениями даты и времени. Что касается последних, то они ограничиваются лишь функциями, возвращающими системную дату/время.
    Например, функция CURRENT_TIMESTAMP возвращает сразу и дату, и время. Плюс имеются функции возвращающие что-либо одно.
    Естественно, в силу такой ограниченности, реализации языка расширяют стандарт за счет добавления функций, облегчающий работу пользователей с данными этого типа. Это обусловлено еще и тем, что на нижнем уровне соответствия стандарту (Entry Level) не требуется поддержка стандартизованных функций этих типов.
    Функция
    DATEADD

    Функция DATEADD (datepart, number, date) возвращает значение типа datetime, которое получается добавлением к дате date количества интервалов типа datepart, равного number (целое число).
    Например, мы можем к заданной дате добавить любое число лет, дней, часов, минут и т. д.
    Допустимые значения аргумента datepart приведены ниже в таблице и взяты из электронной документации к
    SQL
    Server — Books On Line (BOL).
    Datepart
    Допустимые сокращения
    Year — год
    yy, yyyy
    Quarter — квартал
    qq, q
    Month — месяц
    mm, m
    Dayofyear — день года
    dy, y
    Day — день
    dd, d
    Week — неделя
    wk, ww
    Hour — час
    hh
    Minute — минута
    mi, n
    Second — секунда
    ss, s
    Millisecond - миллисекунда ms
    Пусть сегодня 28.10.2005, и мы хотим узнать, какой день будет через неделю.
    Мы можем написать:

    1.
    SELECT
    DATEADD
    (
    day,
    7
    , current_timestamp
    )
    ; а можем и так:
    1.
    SELECT
    DATEADD
    (
    ww,
    1
    , current_timestamp
    )
    ;
    В результате получим одно и то же значение; что-то типа 2005-11-04 00:11:28.683.
    Однако мы не можем в этом случае написать:
    1.
    SELECT
    DATEADD
    (
    mm,
    1
    /
    4
    , current_timestamp
    )
    ; и не потому, что четверть месяца не равна в точности неделе, а потому, что дробная часть значения аргумента datepart отбрасывается, и мы получим 0 вместо одной четвертой и, как следствие, текущий день.
    Кроме того, мы можем использовать вместо CURRENT_TIMESTAMP функцию
    T-SQL
    GETDATE() с тем же самым эффектом. Наличие двух идентичных функций поддерживается, видимо, в ожидании последующего развития стандарта.
    Пример 7.1.1
    Определить, какой будет день через неделю после последнего
    полета.
    Примечание:
    В примерах данной главы используется база данных
    «Аэрофлот». Описание этой схемы и всех остальных схем,
    используемых в настоящее время на сайте для решения задач,
    можно найти в Примечании 1.
    1.
    SELECT
    DATEADD
    (
    day,
    7
    ,
    (
    SELECT
    MAX
    (
    date
    )
    max_date
    2.
    FROM
    pass_in_trip

    3.
    )
    4.
    )
    ;
    Применение подзапроса в качестве аргумента допустимо, так как этот подзапрос возвращает единственное значение типа datetime.
    На примере задачи 7.1.1
    рассмотрим добавление интервала к дате для других
    СУБД.
    MySQL
    MySQL имеет похожую функцию с непохожими аргументами. Вот синтаксис этой функции:
    1. DATE_ADD
    (
    date, INTERVAL value addunit
    )
    Здесь
    date - дата, к которой прибавляется интервал;
    value - величина интервала;
    addunit - тип интервала.
    Допустимы следующие типы интервалов, имена которых говорят сами за себя:
    MICROSECOND
    SECOND
    MINUTE
    HOUR
    DAY
    WEEK
    MONTH
    QUARTER

    YEAR
    SECOND_MICROSECOND
    MINUTE_MICROSECOND
    MINUTE_SECOND
    HOUR_MICROSECOND
    HOUR_SECOND
    HOUR_MINUTE
    DAY_MICROSECOND
    DAY_SECOND
    DAY_MINUTE
    DAY_HOUR
    YEAR_MONTH
    Решение нашей задачи для MySQL примет вид:
    1.
    SELECT
    DATE_ADD
    ((
    SELECT
    MAX
    (
    date
    )
    FROM
    pass_in_trip
    )
    ,
    2. interval
    7
    day
    )
    next_wd;
    next_wd
    2005-12-06 00:00:00
    Чтобы добавить интервал, представляющий собой несколько компонентов времени, используется подстрока из стандартного представления
    даты/времени. Так, например, чтобы добавить к '2018-01-27T13:00:00' один день и 3 часа, можно написать:
    1.
    SELECT
    DATE_ADD
    (
    '2018-01-27T13:00:00'
    , interval
    '1T3'
    DAY_HOUR
    )
    ;
    2018-01-28 16:00:00
    Добавление 1 дня и 15 секунд будет выглядеть так:
    1.
    SELECT
    DATE_ADD
    (
    '2018-01-27T13:00:00'
    , interval
    '01T00:00:15'
    DAY_SECOND
    )
    ;
    2018-01-28 13:00:15
    PostgreSQL и Oracle
    Эти СУБД не используют функцию. Для добавления интервала применяется обычный оператор сложения "+":
    1.
    SELECT
    MAX
    (
    "date"
    )
    + interval
    '7'
    day next_wd
    2.
    FROM
    pass_in_trip;
    Обратите внимание, что величина интервала должна иметь символьный тип данных.
    Добавить 1 день и 3 часа
    PostgreSQL
    У PostgreSQL нет составных интервалов, поэтому можно либо выразить величину интервала в терминах меньшего интервала

    1.
    SELECT
    timestamp
    '2018-01-27T13:00:00'
    + interval
    '27'
    hour; либо добавить два интервала
    1.
    SELECT
    timestamp
    '2018-01-27T13:00:00'
    + interval
    '3'
    hour
    + interval
    '1'
    day;
    Аналогично можно поступить для добавления одного дня и 15 секунд, например:
    1.
    SELECT
    timestamp
    '2018-01-27T13:00:00'
    + interval
    '15'
    second + interval
    '1'
    day;
    1   ...   20   21   22   23   24   25   26   27   ...   47


    написать администратору сайта