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

  • WITH VALUES : 1. ALTERTABLE Product ADD available VARCHAR(20)DEFAULTYesWITHVALUES; Ссылочная целостность

  • PRIMARY KEY

  • SET DEFAULT

  • REFERENCES

  • Вложенные запросы в проверочных ограничениях

  • Проверочное ограничение уровня таблицы

  • INFORMATION_SCHEMA и Oracle Информационная схема (INFORMATION_SCHEMA

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


    Скачать 7.88 Mb.
    НазваниеУчебник по sql если вы хотите узнать, что такое sql этот сайт для вас
    Анкорлекция
    Дата21.12.2022
    Размер7.88 Mb.
    Формат файлаpdf
    Имя файлаMoiseenko_SQL.pdf
    ТипУчебник
    #857633
    страница41 из 47
    1   ...   37   38   39   40   41   42   43   44   ...   47
    maker
    model
    type
    add_date
    A
    1125
    PC
    2015-08-24 22:21:23.310
    Замечания.
    1. Если значение по умолчанию не указано, то подразумевается default
    NULL, т.е. NULL-значение. Естественно, это значение по умолчанию может быть использовано только в том случае, если на столбце нет ограничения
    NOT NULL.
    2. Если добавить столбец в существующую таблицу, то он, согласно стандарту, будет заполнен значениями по умолчанию для имеющихся строк.
    В SQL Server поведение при добавлении столбца несколько отличается от стандартного. Если выполнить запрос

    1.
    ALTER
    TABLE
    Product
    ADD
    available VARCHAR
    (
    20
    )
    DEFAULT
    'Yes'
    ; который добавляет в таблицу Product столбец available со значением по умолчанию ‘yes’, то, как это ни странно, столбец будет заполнен NULL- значениями. Чтобы «заставить» сервер заполнить столбец значениями ‘yes’, можно использовать один из двух способов: a). Запретить NULL, т.е. написать такой запрос:
    1.
    ALTER
    TABLE
    Product
    ADD
    available VARCHAR
    (
    20
    )
    NOT
    NULL
    DEFAULT
    'Yes'
    ;
    Ясно, что этот способ не годится, если столбец допускает значения NULL. b). Использовать специальное предложение WITH VALUES:
    1.
    ALTER
    TABLE
    Product
    ADD
    available VARCHAR
    (
    20
    )
    DEFAULT
    'Yes'
    WITH
    VALUES
    ;
    Ссылочная
    целостность:
    внешний ключ
    (FOREIGN
    KEY)
    Внешний ключ – это ограничение, которое поддерживает согласованное состояние данных между двумя таблицами, обеспечивая так называемую ссылочную целостность. Этот тип целостности означает, что всегда есть возможность получить полную информацию об объекте, распределенную по нескольким таблицам.

    Причины такого распределения, связанные с принципами проектирования реляционной модели, мы рассмотрим в дальнейшем.
    Связь между таблицами не является равноправной. В ней всегда есть главная таблица и таблица подчиненная. Связи бывают двух типов:
    «один к одному» и «один ко многим». Связь «один к одному» означает, что строке главной таблицы соответствует не более одной строки (т.е. одна или ни одной) в подчиненной таблице. Связь «один ко многим» означает, что одной строке главной таблицы отвечает любое число строк (в том числе и
    0) в подчиненной таблице.
    Связь устанавливается посредством равенства значений определенных столбцов в главной и подчиненной таблицах. При этом столбец (или набор столбцов в случае составного ключа) в подчиненной таблице, который соотносится со столбцом (или набором столбцов) в главной таблице, и называется внешним ключом.
    Поскольку главная таблица всегда находится со стороны «один», то столбец, участвующий в связи по внешнему ключу, должен иметь ограничение
    PRIMARY
    KEY или UNIQUE
    Внешний же ключ задается при создании или изменении структуры подчиненной таблицы при помощи спецификации FOREIGN KEY:
    1.
    FOREIGN
    KEY
    (
    <список столбцов
    1
    >
    REFERENCES
    <имя главной таблицы>
    (
    <список столбцов
    2
    >
    )
    Количество столбцов в списках 1 и 2 должно быть одинаковым, а типы данных этих столбцов должны быть попарно совместимы.
    Вот как можно создать внешний ключ в таблице PC:
    1.
    ALTER
    TABLE
    PC

    2.
    ADD
    CONSTRAINT fk_pc_product
    3.
    FOREIGN
    KEY
    (
    model
    )
    REFERENCES
    Product
    (
    model
    )
    ;
    Замечание. Для главной таблицы можно не указывать столбец в скобках, если он является первичным ключом, т.к. он может быть только один. В нашем случае так и есть, поэтому последнюю строку можно было написать в виде
    1.
    FOREIGN
    KEY
    (
    model
    )
    REFERENCES
    Product;
    Аналогичным образом создаются внешние ключи в таблицах Printer и Laptop.
    Теперь пора разобраться с тем, как работает ограничение внешнего ключа.
    Поскольку это ограничение поддерживает согласованность данных в двух таблицах, оно препятствует возникновению таких строк в подчиненной таблице, для которых нет соответствующих строк в главной таблице.
    Рассогласование могло бы возникнуть в результате выполнения следующих действий.
    1. Добавление в подчиненную таблицу строки, для которой нет соответствия в главной таблице. В нашем случае внешние ключи не позволят добавить ни в одну из продукционных таблиц (PC, Laptop или Printer) изделия, модели которого нет в таблице Product. Например, мы получим ошибку при попытке выполнить такой оператор:
    1.
    INSERT
    INTO
    pc
    VALUES
    (
    13
    ,
    1126
    ,
    500
    ,
    64
    ,
    10
    ,
    '24x'
    ,
    650
    )
    ; т.к. модели 1126 нет в таблице Product.
    The INSERT statement conflicted with the FOREIGN KEY constraint
    "fk_pc_product". The conflict occurred in database "learn", table "dbo.product",
    column 'model'. The statement has been terminated.
    (Конфликт инструкции INSERT с ограничением FOREIGN KEY " fk_pc_product ". Конфликт произошел в базе данных "learn", таблица

    "dbo.product", столбец 'model'. Выполнение данной инструкции было прервано.)
    2. Изменение существующего значения внешнего ключа на значение, которого нет в соответствующем столбце главной таблицы. В нашем примере ограничение не позволит выполнить такой оператор
    UPDATE
    1.
    UPDATE
    pc
    SET
    model =
    1126
    WHERE
    model =
    1121
    ; и вернёт аналогичную ошибку.
    3. Удаление строки из главной таблицы, для которой есть связанные строки в подчиненной таблице. Согласованность данных здесь может поддерживаться разными способами, в соответствии со значением опции в необязательном предложении
    1.
    ON
    DELETE
    <опция>
    Возможны следующие значения опции:

    CASCADE каскадное удаление, т.е. при удалении строки из главной таблицы будут удалены также связанные строки из подчиненной таблицы. Например, при удалении модели 1121 из таблицы Product будут удалены строки с кодами 2, 4 и 5 из таблицы PC;

    SET NULL - при удалении строки из главной таблицы значение внешнего ключа становится неопределенным для тех строк из подчиненной таблицы, которые связаны с удаляемой строкой.
    Естественно, этот вариант подразумевает, что на внешнем ключе нет ограничения NOT NULL. В нашем примере с удалением модели 1121 из таблицы Product значение столбца model в таблице PC примет значение
    NULL для строк с кодами 2, 4 и 5;

    SET DEFAULT – действие аналогичное предыдущему варианту, только вместо NULL будет использовано значение по умолчанию;

    NO ACTION (принимается по умолчанию) – операция выполнена не будет, если для удаляемой строки существуют связанные строки в подчиненной таблице. Если связанных строк нет, то удаление будет выполнено.

    Поскольку при создании внешнего ключа для таблицы PC мы не указали никакой опции, то будет использоваться NO ACTION – опция, принимаемая по умолчанию. Чтобы изменить поведение, скажем, на каскадное удаление, мы должны переписать ограничение внешнего ключа. Сделать это можно следующим образом:
    - удалить существующее ограничение;
    - создать новое ограничение.
    Для удаления ограничения также используется оператор ALTER TABLE:
    1.
    ALTER
    TABLE
    <имя таблицы>
    2.
    DROP
    CONSTRAINT <имя ограничения>;
    Вот где нам понадобилось имя ограничения! Давайте удалим внешний ключ из таблицы PC.
    1.
    ALTER
    TABLE
    PC
    2.
    DROP
    CONSTRAINT fk_pc_product;
    Примечание:
    При удалении внешнего ключа сами столбцы не удаляются,
    удаляется лишь ограничение. Это также справедливо и для
    других ограничений.
    Создадим теперь новое ограничение, использующее каскадное удаление:
    1.
    ALTER
    TABLE
    PC
    2.
    ADD
    CONSTRAINT fk_pc_product
    3.
    FOREIGN
    KEY
    (
    model
    )
    REFERENCES
    Product
    ON
    DELETE
    CASCADE;
    4. Изменение значений столбцов в главной таблице, с которыми связан внешний ключ в подчиненной таблице, т.е. тех столбцов, которые указаны в предложении REFERENCES ограничения FOREIGN KEY. Здесь действуют те же варианты, что и в случае с удалением строки из главной таблицы, только опция вводится предложением

    1.
    ON
    UPDATE
    <опция>
    При помощи внешнего ключа, как и других ограничений, мы моделируем связи, которые существуют в предметной области. Поэтому выбор опций определяется именно предметной областью. В нашем случае при изменении номера модели в таблице Product естественно создать ограничение с опцией CASCADE, чтобы это изменение проникало в продукционные таблицы, удаляя изделия аннулированной модели, т.е. для таблицы PC нам следует написать:
    1.
    ALTER
    TABLE
    PC
    2.
    ADD
    CONSTRAINT fk_pc_product
    3.
    FOREIGN
    KEY
    (
    model
    )
    REFERENCES
    Product
    4.
    ON
    DELETE
    CASCADE
    5.
    ON
    UPDATE
    CASCADE;
    Однако для другой предметной области каскадное удаление может привести к ошибочной потере данных. Пусть, например, для таблиц Сотрудники и
    Отделы существует связь по номеру отдела. Если при удалении
    (расформировании) отдела сотрудники не увольняются, а переводятся в другие отделы, то каскадное удаление ошибочно привело бы к удалению информации о сотрудниках, работавших в этом отделе. Здесь подошел бы вариант NO ACTION – чтобы сначала распределить сотрудников по другим отделам, а потом удалить «пустой» отдел; или вариант SET NULL, т.е. сначала удаляем отдел, а потом занимаемся трудоустройством сотрудников, не приписанных ни к какому отделу. Еще раз повторю, что выбор варианта зависит не от предпочтений программиста, а от процессов, имеющих место в реальном мире.
    Замечания
    1. Между таблицами Product и PC выше мы реализовали связь «один ко многим». Связь «один к одному» создается в случае, когда в подчиненной таблице внешним ключом является уникальный столбец или уникальная комбинация столбцов. В ряде случаев связь «один к одному» является ошибкой проектирования, поскольку фактически одна сущность разбивается на две. Однако для такого разделения иногда имеются веские основания, например, когда с целью повышения производительности или обеспечения безопасности приходится выполнить вертикальное секционирование
    (partitioning) таблицы.

    2. При удалении ограничения необходимо знать его имя. Однако, как мы уже знаем, можно создать ограничение, не давая ему имени. Как быть в этом случае? Если мы явно не указываем имя ограничения, его генерирует система. Поэтому имя всегда есть. Другой вопрос, что мы его не знаем. Тут уместно сказать, что в реляционных системах метаданные хранятся так же, как и данные, т.е. в таблицах. Стандартным представлением метаданных является информационная схема, к которой можно адресовать обычные запросы на выборку. Не углубляясь в детали, напишем запрос, который вернет нам имя ограничения внешнего ключа для таблицы PC:
    1.
    SELECT
    CONSTRAINT_NAME
    2.
    FROM
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    3.
    WHERE
    TABLE_NAME =
    'PC'
    AND
    CONSTRAINT_TYPE =
    'FOREIGN
    KEY'
    ;
    Вложенные
    запросы в
    проверочных
    ограничениях
    Мы уже многое сделали, чтобы наша реляционная модель соответствовала предметной области. Однако некоторые проблемы, нарушающие согласованность данных, остались. Например, мы можем добавить в таблицу PC модель (1288), которая в таблице Product объявлена как принтер:
    1.
    INSERT
    INTO
    PC
    VALUES
    (
    13
    ,
    1288
    ,
    500
    ,
    64
    ,
    10
    ,
    '24x'
    ,
    650
    )
    ;
    Более того, ничто не мешает нам добавить эту модель во все продукционные таблицы – PC, Laptop, Printer.
    Итак, нам требуется ограничение, которое бы запретило иметь в подчиненных таблицах продукты несоответствующего типа.

    Сформулируем проверочное ограничение, которое будет определять тип модели по таблице Product и сравнивать его с типом продукционной таблицы.
    Например, для таблицы PC такое ограничение могло бы иметь вид:
    1.
    ALTER
    TABLE
    PC
    2.
    ADD
    CONSTRAINT model_type
    3.
    CHECK
    (
    'PC'
    =
    (
    SELECT
    type
    FROM
    Product pr
    WHERE
    pr.model
    = pc.model
    ))
    ;
    При попытке выполнить вышеприведенный код (вполне легитимный с точки зрения стандарта SQL-92) получаем сообщение об ошибке:
    Subqueries are not allowed in this context. Only scalar expressions are allowed.
    (Вложенные запросы в данном контексте запрещены. Допускаются только скалярные выражения.)
    Другими словами,
    SQL
    Server не допускает использования подзапросов в ограничении CHECK. Что касается реализаций, то это, кстати, больше правило, чем исключение. Что касается MySQL, то эта СУБД вообще не поддерживает ограничений CHECK.
    Восполнить этот пробел в SQL Server позволяет использование функций пользователя (UDF). Трюк состоит в следующем.
    Поскольку, как это следует из сообщения об ошибке, в ограничении CHECK допускаются лишь скалярные выражения, напишем скалярнозначную функцию, которая будет принимать номер модели и возвращать ее тип, указанный в таблице Product. Затем эту функцию мы будем использовать в ограничении. Итак,
    1.
    CREATE
    FUNCTION
    get_type
    (
    @model VARCHAR
    (
    50
    ))
    2. RETURNS VARCHAR
    (
    50
    )
    3.
    AS
    4. BEGIN
    5.
    RETURN
    (
    SELECT
    type
    FROM
    Product
    WHERE
    model=@model
    )
    6.
    END
    ;

    Теперь добавим ограничение:
    1.
    ALTER
    TABLE
    PC
    2.
    ADD
    CONSTRAINT model_type
    CHECK
    (
    'PC'
    = dbo.get_type
    (
    model
    ))
    ;
    Теперь при попытке вставить в таблицу PC модель принтера, например:
    1.
    INSERT
    INTO
    PC
    VALUES
    (
    13
    ,
    1288
    ,
    500
    ,
    64
    ,
    10
    ,
    '24x'
    ,
    650
    )
    ; мы получаем следующее сообщение об ошибке:
    The INSERT statement conflicted with the CHECK constraint "model_type". The
    conflict occurred in database "learn", table "dbo.pc", column 'model'.
    (Конфликт инструкции INSERT с ограничением CHECK "model_type".
    Конфликт произошел в базе данных "learn", таблица "dbo.pc", столбец 'model'.
    Выполнение данной инструкции было прервано.)
    Модель же соответствующего типа можно добавить в таблицу:
    1.
    INSERT
    INTO
    PC
    VALUES
    (
    13
    ,
    1260
    ,
    500
    ,
    64
    ,
    10
    ,
    '24x'
    ,
    650
    )
    ;
    Надеюсь, что вам не составит труда написать подобные ограничения и для остальных таблиц этой схемы.
    Проверочное
    ограничение
    уровня таблицы
    В описании схемы «
    Окраска
    » утверждается, что объем краски одного цвета на квадрате не может превышать 255 единиц. Как реализовать это ограничение? Рассмотренные ранее варианты нам
    не подойдут, т.к. каждая строка таблицы utB может отвечать всем ограничениям на отдельную окраску, но суммарный объем при этом может превысить допустимый предел. Ограничение подобного типа называется ограничением уровня таблицы, т.е. при проверке оно адресуется не к отдельной строке, которой коснулось изменение, а ко всей таблице.
    Поскольку тут нам опять потребуется запрос в ограничении CHECK, что не реализовано, напишем сначала пользовательскую функцию, которая будет возвращать 1, если объем какой- либо краски на каком-либо квадрате превысил 255 единиц, и ноль – в противном случае. Лежащий в основе
    UDF
    запрос достаточно прост
    – группировка по ИД квадрата и цвету с фильтрацией в предложении HAVING по условию, что сумма краски превысила 255. Если такой запрос будет содержать строки, то функция вернет 1, иначе – 0. Собственно функция:
    1.
    CREATE
    FUNCTION
    check_volume
    ()
    2. RETURNS INT
    3.
    AS
    4. BEGIN
    5. DECLARE @ret int
    6.
    IF
    EXISTS
    (
    SELECT
    SUM
    (
    B_VOL
    )
    7.
    FROM
    utB
    JOIN
    utV
    ON
    b_v_id=v_id
    8.
    GROUP
    BY
    b_q_id, V_COLOR
    9.
    HAVING
    SUM
    (
    B_VOL
    )
    >
    255
    )
    10.
    SELECT
    @ret =
    1
    ELSE
    SELECT
    @ret =
    0
    ;
    11.
    RETURN
    @ret;
    12.
    END
    ;
    Осталось написать совсем простое ограничение – возвращаемое функцией значение равно 0 или не равно 1, - это кому как нравится:
    1.
    ALTER
    TABLE
    utB

    2.
    ADD
    CONSTRAINT square_volume
    CHECK
    (
    dbo.check_volume
    ()
    =
    0
    )
    ;
    Попробуем теперь добавить какой-нибудь краски к белому квадрату (т.е. квадрату, который уже окрашен по максимуму всеми цветами), например, квадрату с b_q_id=1:
    1.
    INSERT
    INTO
    utB
    VALUES
    (
    CURRENT_TIMESTAMP,
    1
    ,
    4
    ,
    10
    )
    ;
    В результате мы получим ошибку:
    The INSERT statement conflicted with the CHECK constraint "square_volume".
    The conflict occurred in database "learn", table "dbo.utb". The statement has been
    terminated.
    (Конфликт инструкции INSERT с ограничением CHECK "square_volume".
    Конфликт произошел в базе данных "learn", таблица "dbo.utb". Выполнение данной инструкции было прервано.)
    В качестве упражнения напишите ограничение, которое запретит использование пустых баллончиков, т.е. когда объем краски, израсходованной из баллончика, оказывается более 255.
    INFORMATION_SCHEMA
    и Oracle
    Информационная схема
    (INFORMATION_SCHEMA) является стандартным представлением метаданных в языке
    SQL.
    Исторически каждый производитель реляционных СУБД предоставлял системные таблицы, которые содержали мета- информацию - имена таблиц, столбцов, ограничений, типы данных
    столбцов и т.д. Структура и состав системных таблиц могут меняться в разных версиях продукта, однако поддержка информационной схемы дает возможность менять структуру системных таблиц без изменения способа доступа к метаданным.
    Другим преимуществом применения
    INFORMATION_SCHEMA является то, что запросы к метаданным не зависят от используемой СУБД.
    Из ведущих производителей, пожалуй, только
    1   ...   37   38   39   40   41   42   43   44   ...   47


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