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

  • Вставка строк в таблицу, содержащую автоинкрементируемое поле

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

  • UPDATE

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


    Скачать 7.88 Mb.
    НазваниеУчебник по sql если вы хотите узнать, что такое sql этот сайт для вас
    Анкорлекция
    Дата21.12.2022
    Размер7.88 Mb.
    Формат файлаpdf
    Имя файлаMoiseenko_SQL.pdf
    ТипУчебник
    #857633
    страница23 из 47
    1   ...   19   20   21   22   23   24   25   26   ...   47
    UNION
    ALL предпочтительней UNION даже, если гарантировано отсутствие строк-дубликатов, так как в этом случае не будет выполняться проверка для исключения дубликатов.
    Следует отметить, что вставка нескольких кортежей с помощью конструктора строк уже реализована в
    SQL
    Server 2008. С учетом этой возможности, последний запрос можно переписать в виде:
    1.
    INSERT
    INTO
    Product_D
    VALUES
    2.
    (
    'B'
    ,
    1158
    ,
    'PC'
    )
    ,
    3.
    (
    'C'
    ,
    2190
    ,
    'Laptop'
    )
    ,
    4.
    (
    'D'
    ,
    3219
    ,
    'Printer'
    )
    ;
    Заметим, что MySQL допускает еще одну нестандартную синтаксическую конструкцию, выполняющую вставку строки в таблицу в стиле оператора
    UPDATE
    :

    1.
    INSERT
    [
    INTO
    ]
    <имя таблицы>
    2.
    SET
    {
    <имя столбца>=
    {
    <выражение> |
    DEFAULT
    }}
    , ...
    Рассмотренный в начале параграфа пример с помощью этого оператора можно переписать так:
    1.
    INSERT
    INTO
    Product
    2.
    SET
    maker =
    'B'
    ,
    3. model =
    1157
    ,
    4. type =
    'PC'
    ;
    Вставка строк в
    таблицу, содержащую
    автоинкрементируемое
    поле
    Многие коммерческие продукты допускают использование автоинкрементируемых столбцов в таблицах, то есть столбцов, значение которых формируется автоматически при добавлении новых записей.
    Такие столбцы широко используются в качестве первичных ключей таблицы, так как они автоматически обеспечивают уникальность за счет того, что генерируемые значения не повторяются. Типичным примером столбца такого типа является последовательный счетчик, который при вставке строки генерирует значение на единицу большее предыдущего значения (значения, полученного при вставке предыдущей строки).

    Ниже приводится пример создания таблицы
    Printer_Inc с автоинкрементируемым столбцом
    (code) в MS
    SQL
    Server.
    1.
    CREATE
    TABLE
    Printer_Inc
    2.
    (
    3. code int IDENTITY
    (
    1
    ,
    1
    )
    PRIMARY
    KEY
    ,
    4. model varchar
    (
    4
    )
    NOT
    NULL
    ,
    5. color char
    (
    1
    )
    NOT
    NULL
    ,
    6. type varchar
    (
    6
    )
    NOT
    NULL
    ,
    7. price float
    NOT
    NULL
    8.
    )
    ;
    Автоинкрементируемое поле определяется посредством конструкции
    IDENTITY (1, 1). При этом первый параметр свойства IDENTITY (1) определяет, с какого значения начнется отсчет, а второй, — какой шаг будет использоваться для приращения значения. Таким образом, в нашем примере первая вставленная запись будет иметь в столбце code значение 1, вторая — 2 и т. д.
    Поскольку в поле code значение формируется автоматически, оператор
    1.
    INSERT
    INTO
    Printer_Inc
    2.
    VALUES
    (
    15
    ,
    3111
    ,
    'y'
    ,
    'laser'
    ,
    599
    )
    ; приведет к ошибке, даже если в таблице нет строки со значением в поле code, равным 15. Поэтому для вставки строки в таблицу просто не будем указывать это поле точно так же, как и в случае использования значения по умолчанию, то есть
    1.
    INSERT
    INTO
    Printer_Inc
    (
    model, color, type, price
    )
    2.
    VALUES
    (
    3111
    ,
    'y'
    ,
    'laser'
    ,
    599
    )
    ;
    В результате выполнения этого оператора в таблицу Printer_Inc будет вставлена информация о модели 3111 цветного лазерного принтера, стоимость
    которого равна $599. В поле code окажется значение, которое только случайно может оказаться равным 15. В большинстве случаев этого оказывается достаточно, так как значение автоинкрементируемого поля, как правило, не несет никакой информации; главное, чтобы оно было уникальным.
    Однако бывают случаи, когда требуется подставить вполне конкретное значение в автоинкрементируемое поле. Например, нужно перенести уже имеющиеся данные во вновь создаваемую структуру; при этом эти данные участвуют в связи «один-ко-многим» со стороны «один». Таким образом, мы не можем допустить тут произвола. С другой стороны, не хочется отказываться от автоинкрементируемого поля, так как оно упростит обработку данных при последующей эксплуатации базы данных.
    Поскольку стандарт языка
    SQL не предполагает наличия автоинкрементируемых полей, то не существует и единого подхода. Здесь мы покажем, как это реализуется в MS SQL Server. Оператор
    1.
    SET
    IDENTITY_INSERT < имя таблицы >
    {
    ON
    | OFF
    }
    ; отключает (значение ON) или включает (OFF) использование автоинкремента. Поэтому чтобы вставить строку со значением 15 в поле code, нужно написать:
    1.
    SET
    IDENTITY_INSERT Printer_Inc
    ON
    ;
    2.
    INSERT
    INTO
    Printer_Inc
    (
    code, model, color, type, price
    )
    3.
    VALUES
    (
    15
    ,
    3111
    ,
    'y'
    ,
    'laser'
    ,
    599
    )
    ;
    Обратите внимание, что список столбцов в этом случае является обязательным, то есть мы не можем написать так:
    1.
    SET
    IDENTITY_INSERT Printer_Inc
    ON
    ;
    2.
    INSERT
    INTO
    Printer_Inc
    3.
    VALUES
    (
    15
    ,
    3111
    ,
    'y'
    ,
    'laser'
    ,
    599
    )
    ; ни, тем более, так:

    1.
    SET
    IDENTITY_INSERT Printer_Inc
    ON
    ;
    2.
    INSERT
    INTO
    Printer_Inc
    (
    model, color, type, price
    )
    3.
    VALUES
    (
    3111
    ,
    'y'
    ,
    'laser'
    ,
    599
    )
    ;
    В последнем случае в пропущенный столбец code значение не может быть подставлено автоматически, так как автоинкрементирование отключено.
    Важно отметить, что если значение 15 окажется максимальным в столбце code, то далее нумерация продолжится со значения 16. Естественно, если включить автоинкрементирование:
    1.
    SET
    IDENTITY_INSERT Printer_Inc OFF;
    Наконец, рассмотрим пример вставки данных из таблицы Product в таблицу
    Product_Inc, сохранив значения в поле code:
    1.
    SET
    IDENTITY_INSERT Printer_Inc
    ON
    ;
    2.
    INSERT
    INTO
    Printer_Inc
    (
    code, model,color,type,price
    )
    3.
    SELECT
    *
    FROM
    Printer;
    По поводу автоинкрементируемых столбцов следует добавить следующее.
    Пусть последнее значение в поле code было равно 16, после чего строка с этим значением была удалена. Какое значение будет в этом столбце после вставки новой строки? Правильно, 17, так как последнее значение счетчика сохраняется, несмотря на удаление строки, его содержащей. Поэтому нумерация значений в результате удаления и добавления строк не будет последовательной. Это является еще одной причиной для вставки строки с заданным (пропущенным) значением в автоинкрементируемом столбце.
    Рассмотрим теперь таблицу с единственным автоинкрементируемым столбцом (SQL Server):
    1.
    CREATE
    TABLE
    test_Identity
    (
    2. id int IDENTITY
    (
    1
    ,
    1
    )
    PRIMARY
    KEY
    3.
    )
    ;

    Как вставить в нее строки? Попытка не указывать значение
    1.
    INSERT
    INTO
    test_Identity
    VALUES
    ()
    ; или использовать значение по умолчанию
    1.
    INSERT
    INTO
    test_Identity
    VALUES
    (
    DEFAULT
    )
    ;
    к успеху не приводит - ошибка.
    Понятно, что мы можем вставить конкретное значение, если отключим счетчик:
    1.
    SET
    IDENTITY_INSERT test_Identity
    ON
    ;
    2.
    INSERT
    INTO
    test_Identity
    (
    id
    )
    VALUES
    (
    5
    )
    ;
    3.
    SELECT
    *
    FROM
    test_Identity; но тогда в нем нет для нас никакого смысла.
    Уточним вопрос: как вставить в таблицу именно последовательные значения счетчика? Оказывается, что ответ лежит на поверхности, а именно, в стандартном синтаксисе:
    1.
    SET
    IDENTITY_INSERT test_Identity OFF;
    2.
    INSERT
    INTO
    test_Identity
    DEFAULT
    VALUES
    ;
    Вряд ли вы будете использовать
    DEFAULT VALUES
    в других случаях, т.к. при наличии первичного ключа воспользоваться значениями по умолчанию для всех столбцов таблицы можно будет только один раз. Тут же мы можем повторить этот оператор столько раз, сколько последовательных значений счетчика нам потребуется добавить в таблицу.

    Обратимся теперь к другим СУБД, которые имеют в своем арсенале автоинкрементируемые столбцы.
    MySQL
    MySQL не поддерживает предложения DEFAULT VALUES. Вставить строку со значениями по умолчанию в таблицу можно другим стандартным способом, используя ключевое слово DEFAULT для каждого столбца таблицы - VALUES(DEFAULT, DEFAULT, ...).
    А как здесь вставить очередное значение счетчика в единственный автоинкрементируемый столбец?
    1.
    CREATE
    TABLE
    test_Identity
    (
    2. id int
    (
    11
    )
    NOT
    NULL
    AUTO_INCREMENT
    ,
    3.
    PRIMARY
    KEY
    (
    id
    )
    4.
    )
    ;
    Очень просто. Оказывается будут работать те интуитивные приемы, которые мы безуспешно пытались применить в случае SQL Server, а именно, так
    1.
    INSERT
    INTO
    test_Identity
    VALUES
    ()
    ; или так
    1.
    INSERT
    INTO
    test_Identity
    VALUES
    (
    DEFAULT
    )
    ;
    После выполнения обоих этих операторов получим:
    id
    1
    2
    Заметим, что после вставки конкретного значения в автоинкрементируемый столбец (в MySQL это можно сделать обычным оператором вставки),
    которое будет превышать максимальное имеющееся, приращение счетчика продолжится уже с него. Например:
    1.
    INSERT
    INTO
    test_Identity
    VALUES
    (
    8
    )
    ;
    2.
    INSERT
    INTO
    test_Identity
    VALUES
    (
    DEFAULT
    )
    ;
    3.
    SELECT
    *
    FROM
    test_Identity;
    id
    1
    2
    8
    9
    PostgreSQL
    1.
    CREATE
    TABLE
    identity_table
    (
    id serial
    PRIMARY
    KEY
    )
    ;
    Для вставки очередных значений счетчика мы можем воспользоваться следующими рассмотренными выше приемами:
    1.
    INSERT
    INTO
    identity_table
    DEFAULT
    VALUES
    ;
    2.
    INSERT
    INTO
    identity_table
    VALUES
    (
    DEFAULT
    )
    ;
    3.
    INSERT
    INTO
    identity_table
    (
    id
    )
    VALUES
    (
    DEFAULT
    )
    ;
    4.
    SELECT
    *
    FROM
    identity_table;
    id
    1
    2
    3

    Однако, если вставить конкретное значение (превышающее максимальное значение, достигнутое счетчиком)
    1.
    INSERT
    INTO
    identity_table
    (
    id
    )
    VALUES
    (
    5
    )
    ; и продолжить заполнять значения счетчика,
    1.
    INSERT
    INTO
    identity_table
    VALUES
    (
    DEFAULT
    )
    ; то нумерация продолжается не с максимального значения, а с последнего достигнутого при генерации:
    id
    1
    2
    3
    5
    4
    При этом, когда счетчик достигает 5 при генерации очередного значения, получаем ошибку, связанную с нарушением ограничения первичного ключа:
    ERROR: duplicate key value violates unique constraint "identity_table_pkey"
    DETAIL: Key (id)=(5) already exists.
    Если же таблица не имеет ключа на автоинкрементируемом столбце, то мы получим дубликаты, после чего нумерация продолжится дальше. Вот скрипт, который поясняет сказанное:
    1.
    CREATE
    TABLE
    identity_table_wo
    (
    id serial
    )
    ;
    2.
    INSERT
    INTO
    identity_table_wo
    (
    id
    )
    VALUES
    (
    DEFAULT
    )
    ;
    3.
    INSERT
    INTO
    identity_table_wo
    (
    id
    )
    VALUES
    (
    2
    )
    ;
    4.
    INSERT
    INTO
    identity_table_wo
    (
    id
    )
    VALUES
    (
    DEFAULT
    )
    ,
    (
    DEFAULT
    )
    ;

    5.
    SELECT
    *
    FROM
    identity_table_wo;
    id
    1
    2
    2
    3
    Как сбросить значение счетчика в заданное значение (MySQL)?
    Воспользуемся таблицей, рассмотренной на предыдущей странице
    , и вставим в неё 3 строки.
    1.
    CREATE
    TABLE
    test_Identity
    (
    2. id int
    (
    11
    )
    NOT
    NULL
    AUTO_INCREMENT
    ,
    3.
    PRIMARY
    KEY
    (
    id
    )
    4.
    )
    ;
    5.
    INSERT
    INTO
    test_Identity
    VALUES
    ()
    ,
    ()
    ,
    ()
    ;
    6.
    SELECT
    *
    FROM
    test_Identity;
    id
    1
    2
    3
    Если мы удалим последнюю строку, нумерация продолжится не с 3, а с 4. Т.е. последнее значение счётчика сохраняется и используется при последующем добавлении строк:

    1.
    DELETE
    FROM
    test_Identity
    WHERE
    id=
    3
    ;
    2.
    INSERT
    INTO
    test_Identity
    VALUES
    ()
    ;
    3.
    SELECT
    *
    FROM
    test_Identity;
    id
    1
    2
    4
    Возникает вопрос: "А можно ли сделать так, чтобы нумерация продолжилась с последнего имеющегося значения?" Оставляя в стороне вопрос о том, зачем это нужно, ответим - можно. Но устанавливать это значение счётчика нужно вручную. Итак,
    1.
    DELETE
    FROM
    test_Identity
    WHERE
    id=
    4
    ;
    2.
    ALTER
    TABLE
    test_Identity
    AUTO_INCREMENT
    =
    3
    ;
    3.
    INSERT
    INTO
    test_Identity
    VALUES
    ()
    ,
    ()
    ,
    ()
    ;
    4.
    SELECT
    *
    FROM
    test_Identity;
    id
    1
    2
    3
    4
    5

    Конструктор
    значений
    таблицы
    Синтаксис конструктора значений таблицы:
    1.
    VALUES
    2.
    (
    <элемент конструктора>, <элемент конструктора>, ...
    )
    ,
    3.
    (
    <элемент конструктора>, <элемент конструктора>, ...
    )
    ,
    4. ...
    5.
    (
    <элемент конструктора>, <элемент конструктора>, ...
    )
    При этом элементом конструктора может быть:
    - выражение, вычисляющее значение, совместимое с типом данных соответствующего столбца таблицы;
    -
    DEFAULT
    - для подстановки значения по умолчанию для соответствующего столбца таблицы;
    - NULL;
    - подзапрос, возвращающий одно значение, совместимое с типом данных соответствующего столбца таблицы.
    Конструктор значений таблицы может использоваться для вставки набора строк в существующую таблицу с помощью одного оператора INSERT
    Создадим следующую таблицу для выполнения примеров:
    1.
    CREATE
    TABLE
    Items
    (
    2. item_no int
    PRIMARY
    KEY
    ,
    3. maker char
    (
    10
    )
    ,
    4. type char
    (
    10
    )
    DEFAULT
    'PC'
    ,
    5. value int
    6.
    )
    ;
    Вставим в таблицу 4 строки, используя конструктор.
    1.
    INSERT
    INTO
    Items
    VALUES
    2.
    (
    1
    ,
    'A'
    ,
    'Laptop'
    ,
    12
    )
    ,

    3.
    (
    2
    ,
    'B'
    ,
    DEFAULT
    ,
    NULL
    )
    ,
    4.
    (
    3
    ,
    'C'
    ,
    'Printer'
    ,
    (
    SELECT
    CAST
    (
    model
    AS
    int
    )
    FROM
    Printer
    WHERE
    code=
    1
    ))
    ,
    5.
    (
    4
    ,
    'C'
    ,
    'Printer'
    ,
    (
    SELECT
    CAST
    (
    model
    AS
    int
    )
    FROM
    Printer
    WHERE
    code=
    77
    ))
    ;
    1.
    SELECT
    *
    FROM
    Items;
    item_no
    maker
    type
    value
    1
    A
    Laptop 12
    2
    B
    PC
    NULL
    3
    C
    Printer
    3001
    4
    C
    Printer
    NULL
    Последнее значение в двух последних строках было получено с помощью подзапроса, который возвращает либо одно значение (поскольку выполняется отбор по ключу) с номером модели из таблицы Printer, либо ни одного. Последнее имеет место для четвертой строки, поскольку коду 77 не отвечает никакая строка таблицы Printer. В этом случае будет записано
    NULL-значение.
    Конструктор значений таблицы может использоваться также в предложении FROM. В параграфе, посвященном генерации числовой последовательности
    , последний пример, который находит 100 последовательных незанятых номеров моделей, с учетом этой возможности можно переписать более компактно:
    1.
    SELECT
    (
    SELECT
    MAX
    (
    model
    )
    2.
    FROM
    Product
    3.
    )
    +
    5
    *
    5
    *
    (
    a
    -1
    )
    +
    5
    *
    (
    b
    -1
    )
    + c
    AS
    num
    4.
    FROM
    5.
    (
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ,
    (
    4
    )
    ,
    (
    5
    ))
    x
    (
    a
    )
    CROSS
    JOIN
    6.
    (
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ,
    (
    4
    )
    ,
    (
    5
    ))
    y
    (
    b
    )
    CROSS
    JOIN
    7.
    (
    VALUES
    (
    1
    )
    ,
    (
    2
    )
    ,
    (
    3
    )
    ,
    (
    4
    )
    ,
    (
    5
    ))
    z
    (
    c
    )
    8.
    WHERE
    5
    *
    5
    *
    (
    a
    -1
    )
    +
    5
    *
    (
    b
    -1
    )
    + c <=
    100 9.
    ORDER
    BY
    1
    ;

    Еще один пример использования конструктора значений таблицы для трансформации строки в столбец можно увидеть в главе, посвященной оператору
    CROSS APPLY
    UPDATE_Оператор_UPDATE'>Оператор
    UPDATE
    Оператор UPDATE изменяет имеющиеся данные в таблице. Команда имеет следующий синтаксис:
    1.
    UPDATE
    <имя таблицы>
    2.
    SET
    {
    <имя столбца> =
    {
    <выражение для вычисления значения столбца>
    3. |
    NULL
    4. |
    DEFAULT
    }
    ,...
    }
    5.
    [
    {
    WHERE
    <предикат>
    }]
    С помощью одного оператора могут быть заданы значения для любого количества столбцов. Однако в одном и том же операторе UPDATE можно вносить изменения в каждый столбец указанной таблицы только один раз. При отсутствии предложения WHERE будут обновлены все строки таблицы.
    Если столбец допускает NULL-значение, то его можно указать в явном виде.
    Кроме того, можно заменить имеющееся значение на значение по умолчанию
    (DEFAULT) для данного столбца.
    Ссылка на «выражение для вычисления значения столбца» может относиться к текущим значениям в изменяемой таблице. Например, мы можем уменьшить все цены портативных компьютеров на 10 процентов с помощью следующего оператора:
    1.
    UPDATE
    Laptop
    2.
    SET
    price = price*
    0.9
    ;
    Разрешается также значения одних столбцов присваивать другим столбцам.
    Пусть, например, требуется заменить жесткие диски менее 10 Гбайт в
    портативных компьютерах. При этом емкость новых дисков должна составлять половину объема RAM, имеющейся в данных устройствах. Эту задачу можно решить следующим образом:
    1.
    UPDATE
    Laptop
    2.
    SET
    hd = ram/
    2
    WHERE
    hd <
    10
    ;
    Естественно, типы данных столбцов hd и ram должны быть совместимы. Для приведения типов может использоваться выражение
    1   ...   19   20   21   22   23   24   25   26   ...   47


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