Добавление записи

Функция

Определение запроса добавления записи в таблицу.

Спецификация

     
< список столбцов >::=
< метка доступа >::=
< добавляемые данные >::=
< модификаторы запроса >::=
[WITH LOCK] [WAIT | NOWAIT]
[{QUANT | QUANTUM} TIMEOUT время] [WITH PRIORITY приоритет]
< конструктор данных >::=
< запрос выборки >::=
< значение >::=
значимое выражение
| NULL
| DEFAULT
| литерал
| имя последовательности.{currval|nextval}
| GUID
| USER
| SYSDATE
| LASTROWID
| LAST_AUTOINC
| SQL-параметр
| хранимая процедура
| EXTFILE (имя файла[, имя фильтра])
< хранимая процедура >::=
< имя файла >::=
< спецификация файла >::=
< группа >::=
идентификатор | целое положительное число

Синтаксические правила

  1. Опция < метка доступа > поддерживается только в СУБД ЛИНТЕР БАСТИОН.

  2. < Имя объекта > должно задавать пользовательскую базовую или таблицу «в памяти» или обновляемое пользовательское представление.

  3. Допустимые привилегии для < объекта >, заданного < именем объекта >, должны включать INSERT.

  4. < Имена столбцов > должны указывать на столбцы < объекта >, заданного < именем объекта >, один и тот же столбец не должен быть указан более одного раза.

  5. < Имя столбца > должно задавать реальный столбец < объекта >. Указание псевдостолбцов (типа ROWID или ROWTIME) не допускается.

  6. Отсутствие < имен столбцов > подразумевает неявную спецификацию списка, идентифицирующего все столбцы в < имени объекта > согласно их позициям, указанным при создании таблицы.

    create table tab1 (i int, vc varchar(10) default 'unknown', b byte(5));
    insert into tab1 values (1,'System', hex('00fc6733da'));
    insert into tab1 values (12,default, hex('01cc34abee'));
    insert into tab1 values (34,default, null);
    select * from tab1;
    | 1  | System  | 00fc6733da |
    | 12 | unknown | 01CC34ABEE |
    | 34 | unknown | NULL       |
  7. Количество значений в < конструкторе данных > должно быть равно числу столбцов в явном или подразумеваемом < списке столбцов >. При этом считается, что i-е значение относится к i-му столбцу.

    create table tab1 (i int autoinc, vc varchar(50) not null, n numeric default 0, d date, bol boolean);
    insert into tab1(vc, d, bol) values ('АКБ "Промстройбанк"', to_date('23.04.2000','dd.mm.yyyy'), false);
  8. Если в заданном < списке столбцов > не указаны все столбцы < объекта >, то для не упомянутых столбцов заносятся их значения по умолчанию.

  9. Опция VALUES позволяет использовать один или несколько списков вставляемых значений данных.

  10. Максимальное количество < конструкторов данных > в опции VALUES (т.е. добавляемых одновременно записей) в одном < запросе добавления > ограничено допустимой длиной текста SQL-запроса (не более 32 Кбайта).

    create or replace table tst (inv_num int, name char(10));
    
    insert into tst (inv_num, name) values (67,'Компьютер'), (88,'Принтер'), (678,'Клавиатура');
    
    select * from tst;
     INV_NUM     NAME
     -------     ----
    |         67|Компьютер |
    |         88|Принтер   |
    |        678|Клавиатура|

  11. В опции VALUES для значения элемента < конструктора данных > разрешены любые выражения, не содержащие обращений к столбцам < объекта >, например: оператор SELECT (в том числе в виде < table-запроса > и < value-запроса >), вызов пользовательской функции, не содержащей SQL-запросов и т.д.

    CREATE OR REPLACE TABLE Items (
        item_no INT PRIMARY KEY,
        maker CHAR(10),
        type CHAR(10) DEFAULT 'PC',
        value INT
      );
    CREATE OR REPLACE TABLE Printer ( code INT PRIMARY KEY,  model INT);
    INSERT INTO PRINTER VALUES (1, 100), (77, 7700);
    INSERT INTO Items VALUES
      (1, 'A', 'Laptop', 12),
      (2, 'B', DEFAULT, NULL),
      (3, 'C', 'Printer', (SELECT CAST(model AS INT) FROM Printer WHERE code=1)),
      (4, 'C', 'Printer', (SELECT CAST(model AS INT) FROM Printer WHERE code=77));
  12. Если указан < подзапрос >, то количество столбцов таблицы, порождаемой этим < подзапросом >, должно быть равно числу столбцов в явном или подразумеваемом < списке столбцов >. При этом i-й столбец < подзапроса > относится к i-ому столбцу < объекта >.

    create table tab1 (i int, "Модель" varchar(20));
    insert into tab1 select personid, model from auto;
    create table tab1 (i int, "Модель" varchar(20), d date);
    insert into tab1(I, "Модель") select personid, model from auto;

    или

    insert into tab1(I, "Модель") (select personid, model from auto);
  13. Если значение i-го элемента опции VALUES не является NULL-значением, то оно должно позволять автоматически преобразовывать его к типу i-го элемента списка столбцов. Автоматическое преобразование выполняется для следующих пар типов:

    • SMALLINT, INT, BIGINT, DECIMAL – все между собой;

    • REAL, DOUBLE – между собой;

    • SMALLINT, INT, BIGINT, DECIMAL преобразуются в REAL, DOUBLE;

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

    • строка, содержащая дату и/или время, преобразуется в DATE.

  14. Для присвоения NULL-значений столбцу типа EXTFILE допускается использование конструкции EXTFILE (NULL).

    create table tab1 (i int, ext1 extfile root 'c:\linter\ext', ext2 extfile);
    insert into tab1(i, ext1, ext2) values (1, null, extfile(null));
  15. Добавляемое < значение > может быть логическим значением.

    create or replace table tst (i int, b boolean);
    insert into tst values (1,TRUE);
    insert into tst values (2, CAST (NULL as BOOLEAN));
    insert into tst values (3, 2< 1);
    select * from tst;
     I          B
     -           -
    |        1 | T |
    |        2 |   |
    |        3 | F |
  16. Если задана опция DEFAULT VALUES, столбцам присваивается значение по умолчанию. Если для столбца не задано значение по умолчанию, и он может содержать NULL-значение, то вставляется NULL-значение; в противном случае запись не добавляется и выдается код завершения 901 («Не задано значение первичного ключа или NOT NULL столбца»). Транслятор SQL СУБД ЛИНТЕР не проверяет, действительно ли у столбца есть значение по умолчанию, а возможные ошибки выдаются ядром СУБД ЛИНТЕР.

    create table tab1 (i1 int, i2 int default 0, i3 int default 1000, i4 int default -1, vc varchar(20));
    insert into tab1(i1, i2, i3, i4, vc) values (1, default, default, default, 'SYSTEM');
    select * from tab1;
    |1 |0 |1000 |-1 |SYSTEM |
  17. < SQL-параметр > может быть именованный «:имя параметра» или не именованный «?» (см. пункт «SQL-параметр»).

  18. Числовое значение < значимого выражения > допускается представлять в виде строкового значения без использования оператора преобразования типа данных.

    create or replace table tst (i1 int, i2 int, i3 int, db1 double, db2 double);
    insert into tst values (15, '15', cast '15' as int, 103.545, '1.03545e+2');
    select * from tst;
    
    |       15|       15|       15|     103.545|      103.545|

Общие правила

  1. Добавление записей выполняется в следующей последовательности:

    • создается строка-кандидат, структура данных которой совпадает со структурой строки базовой таблицы. Если < имя таблицы > идентифицирует представление, то в качестве базовой таблицы выступает та, из которой создано данное представление;

    • все поля строки-кандидата заполняются значениями по умолчанию;

    • если задана спецификация DEFAULT VALUES, строка-кандидат вставляется в базовую таблицу;

    • для каждого столбца, указанного в < списке столбцов >, значение в строке-кандидате заменяется вставляемым значением;

    • строка-кандидат добавляется в базовую таблицу.

  2. Если < конструктор данных > содержит добавление нескольких записей и одна из этих записей не может быть добавлена (например, переполнение значения, ограничение целостности CHECK и т.п.), то процесс добавления прерывается на ошибочной записи с выдачей соответствующего кода завершения, а ранее добавленные записи удаляются.

  3. При добавлении в BLOB-столбец текстовых данных (типа CHAR, VARCHAR, NCHAR, NCHAR VARYING) выполняется автоматическая перекодировка этих данных в кодировку BLOB-столбца, а бинарные данные добавляются «как есть»:

    create or replace table test(i int, bl blob character set "UCS2");
    insert into test(i,bl) values (1, 'АБВГДЕЁЖ');
    insert into test(i,bl) values (2, n'АБВГДЕЁЖ');
    insert into test(i,bl) values (3, HEX('410042004300440045004600'));
    select i, lenblob(bl), getblobstr(bl, 1, 20) from test;
    |          1|         16|АБВГДЕЁЖ..|
    |          2|         16|АБВГДЕЁЖ..|
    |          3|         12|ABCDEF....|
  4. Если значение для AUTOROWID-столбца не задано при занесении записей в таблицу, содержащую AUTOROWID-столбец, то для каждой записи в него заносится значение, равное ROWID этой записи (здесь возможен как INSERT одной записи, так и INSERT FROM SELECT).

  5. Если значение для AUTOROWID-столбца задано, то запись должна быть занесена в таблицу с ROWID, равным указанному значению. Если означенный ROWID занят другой записью, либо указано недопустимое значение ROWID, то операция завершается с ошибкой. Здесь также возможен как INSERT одной записи, так и INSERT FROM SELECT.

  6. Если < имя объекта > ссылается на необновляемый объект, будет зафиксирована исключительная ситуация 2162 («Данное представление не может быть обновлено»).

  7. При указании спецификации DEFAULT VALUES автоматически выполняются заданные свойства столбца (например, при AUTOINC значение столбца увеличивается на заданную величину).

    create table tab1 ( i int autoinc, c char (10) default '???', d date default sysdate, n dec default 0);
    insert into tab1 default values;
    insert into tab1 default values;
    select * from tab1;
    |1 |??? |28.04.2003:13:10:15.00 |0.0 |
    |2 |??? |28.04.2003:13:10:15.00 |0.0 |
  8. При занесении значения в столбец типа DECIMAL проверяется, удовлетворяет ли оно значениям PRECISION и SCALE, заданным для столбца. Если задано слишком много цифр дробной части, то число округляется; если задано слишком много цифр целой части, выдается код завершения OVRDECIMAL.

    create table tab1 ( d1 dec(4,2), d2 dec(15,7));
    insert into tab1 values (15.347, 45.12345678);
    select * from tab1;
    |15.35 |45.1234568 |
  9. При присвоении по INSERT значения CAST AS < строковый тип > некоторому столбцу без явного указания длины строкового типа длина делается равной длине столбца.

    create table tab1 (c varchar(2700));
    insert into tab1 values (cast '12345' as char);
  10. Если столбец имеет модификатор AUTOINC, добавляемое значение должно быть больше всех ранее добавлявшихся в таблицу значений данного столбца.

    create table tab1 (i int autoinc);
    insert into tab1 default values;
    insert into tab1 values (100);
    select * from tab1;
    |1|
    |100|
  11. Если столбец имеет модификатор AUTOINC RANGE, то можно вставлять произвольные значения вне диапазонов.

    create table tab1 (i int autoinc range (1:100, 500:1000));
    insert into tab1 default values;
    insert into tab1 values (400);
    select * from tab1;
    |1|
    |400|
  12. Возвращаемое < хранимой процедурой > значение должно быть скалярным (не курсорным) и иметь тип данных соответствующего столбца или приводимый к нему.

    Хранимая процедура:
    create or replace procedure insert_tst(in prm int) result char(5)
    code
      return to_char(prm*100);//
    end;
    
    Вставка значения, возвращаемого хранимой процедурой;
    create or replace table tst (id int autoinc, i int, ch char(10));
    insert into tst (i, ch) values(100, '$'+insert_tst(5));
    insert into tst (i, ch) values(200, '$'+insert_tst(? (int)));
    7
    select * from tst;
    |          1|        100|$500      |
    |          2|        200|$700      |
    
  13. Конструкция < ORDER BY-спецификация > задаёт порядок, в котором записи должны добавляться в таблицу.

    Примечание

    В действительности, реальные значения ROWID добавленных в таблицу записей во многих случаях будут не соответствовать порядку добавления записей. Соответствие будет в следующих случаях:

    • если записи заносятся в пустую таблицу;

    • после очистки таблицы;

    • после сжатия таблицы (команда PRESS);

    • в таблице не было удаления записей.

    CREATE OR REPLACE TABLE T1( i int);
    CREATE OR REPLACE TABLE T2( i int);
    insert into t2 (i) values(1);
    insert into t2 (i) values(2);
    insert into t2 (i) values(3);
    insert into t2 (i) values(4);
    insert into t2 (i) values(5);
    
    insert into t1 (i) select * from t2 order by 1 desc;
    select rowid, i from t1;
     ROWID       I
     -----       -
    |          1|          5|
    |          2|          4|
    |          3|          3|
    |          4|          2|
    |          5|          1|
  14. Параметр < время > задает максимально допустимую продолжительность выполнения запроса (от 1 до 65535 сек.). Если запрос в отведенное для него время не был выполнен, его обработка прекращается с выдачей соответствующего кода завершения.

  15. Конструкция WITH PRIORITY < приоритет > устанавливает заданный приоритет (значение в диапазоне от 0 до 255) выполняемому запросу. Если задать приоритет больше текущего приоритета пользователя, от имени которого подается запрос, то выдается код завершения 1022 («Нарушение привилегий»).

  16. Конструкция WITH PRIORITY < приоритет > устанавливает приоритет только тому запросу, в котором она указана. На приоритет любых последующих запросов она не влияет.

  17. При вставке строки в таблицу, содержащую генерируемый столбец, вычисляется ассоциированное с ним < логическое выражение >, и полученное значение становится значением этого столбца в добавляемой записи.

    create or replace table emp (
      emp_no integer,
      emp_sal double,
      emp_bonus double,
      emp_total generated always as (emp_sal + emp_bonus));

    При выполнении оператора добавления записи

    insert into emp (emp_no, emp_sal, emp_bonus) values (1, 40000, 4000);

    путем вычисления выражения emp_sal + emp_bonus будет автоматически сгенерировано значение столбца emp_total, и в таблицу emp будет добавлена запись со значениями (1, 40000, 4000, 44000).

  18. В добавляемой записи вместо явного значения генерируемого столбца можно использовать опцию DEFAULT.

    Приведенные ниже insert-команды эквивалентны.

    create or replace table tst ("Сумма" numeric, "Скидка" numeric, "Итого" generated always as (("Сумма"*(100-"Скидка")/100)));
    insert into tst ("Сумма", "Скидка") values (1000,5);
    insert into tst ("Сумма", "Скидка") values (2000,7);
    select * from tst;
    |    1000.0|   5.0|   950.0|
    |    2000.0|   7.0|  1860.0|
    insert into tst ("Сумма", "Скидка", "Итого") values (1000, 5, default);
    insert into tst ("Сумма", "Скидка", "Итого") values (2000, 7, default);
    select * from tst;
    |    1000.0|   5.0|   950.0|
    |    2000.0|   7.0|  1860.0|
  19. Добавление новых записей в циклическую таблицу из этой же таблицы через подзапрос (INSERT INTO tab FROM SELECT tab) имеет некоторые особенности. Это связано с тем, что при попытке добавить первую запись в переполненную таблицу сначала происходит её автоматическое удаление. А когда ядро СУБД обращается за данными для добавления, выясняется, что исходной записи нет и данные брать уже неоткуда. Поэтому место первой удаленной записи в таблице занимает вторая запись из подзапроса, т.е. добавление записей из подзапроса происходит со сдвигом на одну запись, при этом первая запись подзапроса будет потеряна.

  20. Для таблиц «в памяти» < запрос добавления > в режиме OPTIMISTIC не поддерживается (так же как и другие DML-запросы).

  21. Модификатор WITH LOCK заставляет блокировать добавляемую запись. Разблокирование добавленной записи выполняется после завершения транзакции (COMMIT/ROLLBACK).

    create or replace table tst (i int default 0, c char(20) default 'xxx');
    insert into tst(i,c) values(100,'abc') with lock;
    insert into tst default values with lock;
    insert into tst (i,c) values (100,'abc'), (200, 'def') with lock;
    insert into tst (i,c) select personid, make from auto where rowid=100 with lock;
  22. Накладываемая модификатором WITH LOCK блокировка может подвергаться эскалации, т.е. если суммарное количество блокированных (по командам UPDATE и INSERT) в таблице записей превысит 1000, то блокировка записей сбрасывается и блокируется вся таблица (это означает, что с этого момента все вновь добавляемые записи считаются блокированными).

    Примечание

    Добавляемая запись без модификатора WITH LOCK не блокируется и становится сразу же видимой параллельно работающим транзакциям.

  23. Если добавляемая запись с модификатором WITH LOCK ссылается на заблокированную запись, то выдается код завершения 135 («Строка таблицы заблокирована другим пользователем»).

    create table tpk(i int primary key);
    create table tfk(i int references tpk);
    exclusive
    -- установили транзакционный режим
    insert into tpk values (1) with lock;
    -- здесь транзакции, которые пытаются читать таблицу tpk или только ее запись с i=1, будут ждать снятия блокировки
    -- транзакции, которые пытаются внести запись в таблицу tfk с i=1, ссылающиеся на добавленную запись, получат код завершения 135
    commit;
    -- блокировка снимается

Примеры

  1. Добавление данных в циклическую таблицу

    create or replace table ct(i int);
    alter table ct set records limit 5;
    insert into ct values(1),(2),(3), (4),(5);
    select * from ct;

    Этот select-запрос возвращает следующие 5 записей:

    I
     -
    |          1|
    |          2|
    |          3|
    |          4|
    |          5|
  2. insert into ct(i) select i+10 from ct;
    select * from ct;

    Этот select-запрос возвращает 5 записей, из которых видно, что реально изменились только 4 записи:

     I
     -
    |         12|
    |         13|
    |         14|
    |         15|
    |          5|
  3. Добавление данных с метками мандатного доступа

    username SYSTEM/MANAGER8
    create level "НЕСЕКРЕТНО"=1;
    create level "ДСП"=2;
    
    grant DBA to B identified by '12345678';
    
    alter user B LEVEL("НЕСЕКРЕТНО","НЕСЕКРЕТНО");
    username B/12345678
    
    ! Создание объектов БД (таблиц) и передача прав на них всем
    ! пользователям (разрешение всех действий по дискреционному доступу):
    
    create or replace table TB(I INT LEVEL("НЕСЕКРЕТНО", "НЕСЕКРЕТНО"), C CHAR(20) LEVEL("НЕСЕКРЕТНО", "НЕСЕКРЕТНО")) LEVEL("НЕСЕКРЕТНО", "НЕСЕКРЕТНО");
    
    grant all on TB to PUBLIC;
    
    ! Добавление данных:
    
    insert into tb values(1,'one');
    insert into tb##"НЕСЕКРЕТНО"#"ДСП" values(2,'two');
    insert into tb##"НЕСЕКРЕТНО"#"НЕСЕКРЕТНО" values(3,'three');