Oracle можно ли в запросе применить функцию которая вставляет данные в таблицу

Обновлено: 06.07.2024

Те, кто пришел в Oracle из MSSQL, наверняка столкнулись (как и я) с массой неожиданностей.

create function Foo1 (param1 nvarchar, param2 decimal(18,2))
return table (
id number,
nn nvarchar(50)
)
as
.

Знакомо, не правда ли? Если подобная функция прекрасно возвращала ADO Recordset из MS SQL, то в Oracle такой халявы нет. Однако получать наборы данных из функций через ADO просто необходимо, если мы хотим придерживаться грамотной структуры объектной модели.

Создадим две таблицы — сотрудников и подразделений.

--создание табличных пространств
create tablespace ALEX_DATA datafile 'C:\oracle\user_data\tblsp_alexdata.dat'
size 10M REUSE AUTOEXTEND ON NEXT 2M MAXSIZE 200M;
create tablespace ALEX_INDEX datafile 'C:\oracle\user_data\tblsp_alexix.dat'
size 1M REUSE AUTOEXTEND ON NEXT 1M MAXSIZE 200M;
/
--создание таблиц
create table ALEX.T_EMPLOYEES(
id number(5) not null,
id_department number(5) not null,
empinfo nvarchar2(50) not null
) tablespace ALEX_DATA;
create table ALEX.T_DEPARTMENTS(
id number(5) not null,
depinfo nvarchar2(50) not null
) tablespace ALEX_DATA;
/
--создание индексов
create index IXPK_T_EMPLOYEES on ALEX.T_EMPLOYEES(id)
tablespace ALEX_INDEX;
create index IXPK_T_DEPARTMENTS on ALEX.T_DEPARTMENTS(id)
tablespace ALEX_INDEX;
/
--создание реляционных связей
alter table ALEX.T_DEPARTMENTS
add constraint PK_T_DEPARTMENTS primary key (ID) using index IXPK_T_DEPARTMENTS;
/
alter table ALEX.T_EMPLOYEES
add constraint PK_T_EMPLOYEES primary key (ID) using index IXPK_T_EMPLOYEES
add constraint FK_T_DEPARTMENTS foreign key (id_department)
references ALEX.T_DEPARTMENTS(id);
/
--демо-данные
insert into ALEX.T_DEPARTMENTS (ID, DEPINFO)
values (1, 'Отдел кадров');
insert into ALEX.T_DEPARTMENTS (ID, DEPINFO)
values (2, 'Информационный отдел');
insert into ALEX.T_DEPARTMENTS (ID, DEPINFO)
values (3, 'Бухгалтерия');

insert into ALEX.T_EMPLOYEES (ID, ID_DEPARTMENT, EMPINFO)
values(1, 1, 'Иванов');
insert into ALEX.T_EMPLOYEES (ID, ID_DEPARTMENT, EMPINFO)
values(2, 1, 'Борисов');
insert into ALEX.T_EMPLOYEES (ID, ID_DEPARTMENT, EMPINFO)
values(3, 2, 'Сергеев');
insert into ALEX.T_EMPLOYEES (ID, ID_DEPARTMENT, EMPINFO)
values(4, 3, 'Никитин');
insert into ALEX.T_EMPLOYEES (ID, ID_DEPARTMENT, EMPINFO)
values(5, 3, 'Александров');

Наша цель — написать функцию, которая бы возвращала список сотрудников отдела, id которого передается в качестве параметра.
Для начала нам нужно описать тип данных, возвращаемый таблицей.

--тип данных строки, возвращаемой GetEmployees
type rowGetEmployees is record(
l_empinfo ALEX.T_EMPLOYEES.EMPINFO%TYPE, --привязка к типу поля empinfo
l_depinfo ALEX.T_DEPARTMENTS.DEPINFO%TYPE
);

Это тип данных строки. Атрибут TYPE объявляет для переменной тип, идентичный указанному полю. Создаем второй тип:

type tblGetEmployees is table of rowGetEmployees;

Это таблица из строк типа rowGetEmployees. Переменную этого типа будет возвращать наша функция:

function GetEmployees
(prm_depID number default null)
return tblGetEmployees
pipelined;

Если параметр не передан, будем возвращать список всех сотрудников. Атрибут pipelined означает, что функция является конвейерной, результат возвращается клиенту немедленно при вызове директивы pipe row, поэтому оператор return необязателен. Фактически, по результирующему набору из запроса в теле функции проходит курсор, который при каждой итерации добавляет в рекордсет текущую строку.
Поместим типы данных и функцию в пакет. На выходе имеем

Табличные функции SQL и PL/SQL

Табличной функцией SQL называется функция, которая может вызываться из секции FROM запроса, как если бы она была реляционной таблицей. Коллекции, возвращаемые та­бличными функциями, можно преобразовать оператором TABLE в структуру, к которой можно обращаться с запросами из языка SQL. Табличные функции особенно удобны в следующих ситуациях:

  • Выполнение очень сложных преобразований данных, требующих использования PL/SQL , но с необходимостью обращаться к этим данным из команд SQL .
  • Возвращение сложных результирующих наборов управляющей среде (отличной от PL/SQL ). Вы можете открыть курсорную переменную для запроса, основанного на табличной функции, чтобы управляющая среда могла выполнить выборку данных через курсорную переменную.

Табличные функции открывают массу полезных возможностей для разработчиков PL/SQL . Чтобы продемонстрировать некоторые из этих возможностей, мы поближе познакомимся с потоковыми и конвейерными табличными функциями.

Потоковые табличные функции

Потоковая передача данных позволяет переходить между процессами или стадиями без использования вспомогательных структур данных. Табличные функции в сочетании с выражением CURSOR позволяют организовать потоковую передачу данных через не­сколько промежуточных преобразований в одной команде SQL .

Конвейерные табличные функции

Эти функции возвращают результирующий набор в конвейерном режиме, то есть данные поступают, пока функция продолжает выполняться. Добавьте секцию PARALLEL_ENABLE в заголовок конвейерной функции — и у вас появляется функция, которая будет вы­полняться параллельно в параллельном запросе.

До выхода Oracle Database 12c табличные функции могли возвращать только вложенные таблицы и VARRAY . Начиная с версии 12.1 появилась возможность определения табличных функций, возвращающих ассоциативные массивы с цело­численными индексами, тип которых определяется в спецификации пакета.

Давайте посмотрим, как определяются табличные функции и как использовать их в приложениях.

Вызов функции из секции FROM

Чтобы вызвать функцию из секции FROM , необходимо сделать следующее:

  • Определить тип данных RETURN функции как тип коллекции (вложенная таблица или VARRAY ).
  • Убедиться в том, что все остальные параметры функции имеют режим IN и тип дан­ных SQL . (Например, из запроса не удастся вызвать функцию, аргумент которой относится к логическому типу или типу записи.)
  • Встроить вызов функции в оператор TABLE (в Oracle8i придется использовать опе­ратор cast).

Рассмотрим простой пример использования табличной функции. Мы начнем с создания типа вложенной таблицы на базе объектного типа pets :

Затем создается функция с именем pet_family . В ее аргументах передаются два объекта pet . Далее в зависимости от значения breed возвращается вложенная таблица с инфор­мацией обо всем семействе, определенной в коллекции:

Функция pet_family тривиальна; здесь важно понять, что функция PL/SQL может содержать сколь угодно сложную логику, которая реализуется средствами PL/SQL и выходит за рамки выразительных возможностей SQL .

Теперь эта функция может вызываться в секции FROM запроса :

Часть выходных данных:

Передача результатов вызова табличной функции в курсорной переменной

Табличные функции помогают решить проблему, с которой разработчики сталкивались в прошлом, — а именно как передать данные, полученные в программе PL/SQL (то есть данные, не хранящиеся в таблицах базы данных), в управляющую среду без поддержки PL/SQL ? Курсорные переменные позволяют легко передать результирующие наборы на базе SQL , допустим, в программу Java, потому что курсорные переменные поддер­живаются в JDBC . Но если сначала нужно провести сложные преобразования в PL/ SQL , как вернуть эти данные вызывающей программе?

Теперь эта проблема решается объединением мощи и гибкости табличных функций с ши­рокой поддержкой курсорных переменных в средах без поддержки PL/SQL . Допустим, я хочу сгенеририровать данные семейства животных (полученные вызовом функции pet_family из предыдущего раздела) и передать строки данных интерфейсному приложению, написанному на Java.

Это делается очень просто:

В этой программе я воспользуюсь преимуществами предопределенного слабого курсор­ного типа SYS_REFCURSOR (появившегося в Oracle9i Database ) для объявления курсорной переменной. Курсорная переменная открывается вызовом OPEN FOR и связывается с за­просом, построенным на базе табличной функции pet_family .

Затем курсорная переменная передается интерфейсной части Java . Так как JDBC распознает курсорные переменные, код Java легко выполняет выборку строк данных и интегрирует их в приложение.

Создание потоковой функции

Потоковая функция получает параметр с результирующим набором (через выражение CURSOR ) и возвращает результат в форме коллекции. Так как к коллекции можно при­менить оператор TABLE , а затем запросить данные командой SELECT , эти функции по­зволяют выполнить одно или несколько преобразований данных в одной команде SQL . Потоковые функции, поддержка которых добавилась в Oracle9i Database , позволяют скрыть алгоритмическую сложность за интерфейсом функции, и упростить SQL прило­жения. Приведенный ниже пример объясняет различные действия, которые необходимо выполнить для такого использования табличных функций.

Представьте следующую ситуацию: имеется таблица с информацией биржевых коти­ровок, которая содержит строки с ценами на моменты открытия и закрытия биржи:

Эту информацию необходимо преобразовать в другую таблицу:

Иначе говоря, одна строка stocktable превращается в две строки tickertable . Эту задачу можно решить многими способами. Самое элементарное и традиционное решение на PL/SQL выглядит примерно так:

Также возможны решения, полностью основанные на SQL :

А теперь предположим, что для перемещения данных из stocktable в tickertable требуется выполнить очень сложное преобразование, требующее использования PL/ SQL . В такой ситуации табличная функция, используемая для передачи преобразуемых данных, потребует намного более эффективного решения.

Прежде всего, при использовании табличной функции нужно будет возвращать вложен­ную таблицу или массив VARRAY с данными. Я выбрал вложенную таблицу, потому что для VARRAY нужно задать максимальный размер, а я не хочу устанавливать это ограни­чение в своей реализации. Тип вложенной таблицы должен быть определен как тип на уровне схемы или в спецификации пакета, чтобы ядро SQL могло разрешить ссылку на коллекцию этого типа. Конечно, хотелось бы вернуть вложенную таблицу, основанную на самом определении таблицы, — то есть чтобы определение выглядело примерно так:

К сожалению, эта команда завершится неудачей, потому что %ROWTYPE не относится к числу типов, распознаваемых SQL. Этот атрибут доступен только в разделе объявле­ний PL/SQL . Следовательно, вместо этого придется создать объектный тип, который воспроизводит структуру реляционной таблицы, а затем определить тип вложенной таблицы на базе этого объектного типа:

Чтобы табличная функция передавала данные с одной стадии преобразования на дру­гую, она должна получать аргумент с набором данных — фактически запрос. Это можно сделать только одним способом — передачей курсорной переменной, поэтому в списке параметров функции необходимо будет использовать тип REF CURSOR.

Я создал пакет для типа REF CURSOR , основанного на новом типе вложенной таблицы:

Работа завершается написанием функции преобразования:

Как и в случае с функцией pet_family , конкретный код не важен; в ваших программах логика преобразований будет качественно сложнее. Впрочем, основная последователь­ность действий с большой вероятностью будет повторена в вашем коде, поэтому я при­веду краткую сводку в следующей таблице.

Итак, теперь у меня имеется функция, которая будет проделывать всю нетривиальную, но необходимую работу, и я могу использовать ее в запросе для передачи данных между таблицами:

Внутренняя команда SELECT извлекает все строки таблицы stocktable . Выражение CURSOR , в которое заключен запрос, преобразует итоговый набор в курсорную переменную, которая передается stockpivot. Функция возвращает вложенную таблицу, а оператор TABLE преобразует ее к формату реляционной таблицы, к которой можно обращаться с запросами.

Никакого волшебства, и все же выглядит немного волшебно, правда? Но вас ждет нечто еще более интересное — конвейерные функции!

Создание конвейерной функции

Конвейерной функцией называется табличная функция, которая возвращает результиру­ющий набор как коллекцию, но делает это асинхронно с завершением самой функции. Другими словами, база данных уже не ожидает, пока функция отработает до конца и со­хранит все вычисленные строки в коллекции PL/SQL, прежде чем выдать первые строки. Каждая запись, готовая к присваиванию в коллекцию, передается функцией как по кон­вейеру. В этом разделе описаны основы построения конвейерных табличных функций. Чтобы лучше понять, что необходимо для построения конвейерных функций, мы пере­работаем функцию stockpivot :

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

Строки Описание
2 По сравнению с исходной версией stockpivot добавлено ключевое слово PIPELINED
4-5 Объявление локального объекта и локальной записи, как и в первой версии. В этих
строках интересно то, что не объявляется, — а именно вложенная таблица, которая будет возвращаться функцией. Намек на то, что будет дальше…
7-9 Начало простого цикла с выборкой каждой строки из курсорной переменной; цикл завершается, когда в курсоре не остается данных
12-15 и 19-21 Заполнение локального объекта для строк tickertable (на моменты открытия и закрытия)
16-21 Команда PIPE ROW (допустимая только в конвейерных функциях) немедленно передает
объект, подготовленный функцией
25 В конце исполняемого раздела функция ничего не возвращает! Вместо этого она вызывает RETURN без указания значения (что прежде разрешалось только в процедурах) для возврата управления вызывающему блоку. Функция уже вернула все свои данные командами PIPE ROW

Конвейерная функция вызывается так же, как и неконвейерная. Внешне никакие разли­чия в поведении не проявляются (если только вы не настроили конвейерную функцию для параллельного выполнения в составе параллельного запроса — см. следующий раздел — или не включили логику, использующую асинхронное возвращение данных). Возьмем запрос, использующий псевдостолбец ROWNUM для ограничения строк, вклю­чаемых в выборку:

Мои тесты показывают, что в Oracle Database 10g и Oracle Database 11g при преобра­зовании 100 000 строк в 200 000 и последующем возвращении только первых 9 строк конвейерная версия завершает свою работу за 0,2 секунды, тогда как выполнение не­конвейерной версии занимает 4,6 секунды.

Как видите, конвейерная передача строк работает, и обеспечивает существенный выигрыш!

Активизация параллельного выполнения функции

Одним из огромных достижений PL/SQL , появившихся в Oracle9i Database, стала воз­можность выполнения функций в контексте параллельных запросов. До выхода Oracle9i Database вызов функции PL/SQL в SQL переводил запрос в режим последовательного выполнения — существенная проблема для хранилищ данных большого объема. Теперь в заголовок конвейерной функции можно добавить информацию, которая подскажет исполнительному ядру, каким образом передаваемый функции набор данных следует разбить для параллельного выполнения.

В общем случае функция, предназначенная для параллельного выполнения, должна иметь один входной сильнотипизованный параметр REF CURSOR .

  • Функция может выполняться параллельно, а данные, передаваемые этой функции, могут разбиваться произвольно:

В этом примере ключевое слово ANY выражает утверждение программиста о том, что результаты не зависят от порядка получения входных строк функцией. При ис­пользовании этого ключевого слова исполнительная система случайным образом разбивает данные между процессами запроса. Это ключевое слово подходит для функций, которые получают одну строку, работают с ее столбцами, а затем генери­руют выходные строки по содержимому столбцов только этой строки. Если в вашей программе действуют другие зависимости, результат становится непредсказуемым.

  • Функция может выполняться параллельно, все строки заданного отдела должны передаваться одному процессу, а передача осуществляется последовательно:

Oracle называет такой способ группировки записей кластерным; столбец, по которому осуществляется группировка (в данном случае department ), называется кластерным ключом. Здесь важно то, что для алгоритма несущественно, в каком порядке значений кластерного ключа он будет получать кластеры, и Oracle не гарантирует никакого конкретного порядка получения. Тем самым обеспечивается ускорение работы алгоритма по сравнению с кластеризацией и передачей строк в порядке значений кластерного ключа. Алгоритм выполняется со сложностью N вместо N log(N) , где N — количество записей.

В данном примере в зависимости от имеющейся информации о распределении зна­чений можно выбрать между HASH (department) и RANGE (department). HASH работает быстрее, и является более естественным вариантом для использования с CLUSTER.. .BY .

  • Функция должна выполняться параллельно, а строки, передаваемые конкретному процессу в соответствии с PARTITION. BY (для этого раздела), будут проходить ло­кальную сортировку этим процессом.

Фактически происходит параллелизация сортировки, поэтому команда SELECT , ис­пользуемая для вызова табличной функции, не должна содержать секции ORDER. BY (так как ее присутствие будет противоречить попытке параллелизации сортировки). Следовательно, в данном случае естественно использовать вариант RANGE в сочетании с ORDER. ..BY . Реализация будет работать медленнее, чем CLUSTER. BY , поэтому этот вариант следует использовать только в том случае, если алгоритм зависит от него.

Конструкция CLUSTER. BY не должна использоваться вместе с ORDER. BY в объявлении табличной функции. Это означает, что алгоритм, зависящий от кластеризации по одному ключу cl с последующим упорядочением набора запи­сей с заданным значением cl, скажем, по c2, должен проходить параллелизацию с использованием ORDER. BY в объявлении табличной функции.

Оператор SQL INSERT предназначен для вставки значений столбцов в таблицу баз данных. В результате его применения в таблице базы данных появляется новая строка.

Оператор INSERT имеет следующий синтаксис:

INSERT INTO ИМЯ_ТАБЛИЦЫ [(ИМЕНА СТОЛБЦОВ)] VALUES (ВСТАВЛЯЕМЫЕ_ЗНАЧЕНИЯ)

Квадратные скобки [], в которые заключен элемент запроса (ИМЕНА СТОЛБЦОВ), означают, что этот элемент является необязательным.

Вставка значений в таблицу с указанием или без указания столбцов

Рассмотрим подробнее применение оператора INSERT с указанием имён столбцов и без указания, остановимся на случаях, когда указывать имена столбцов всё же требуется.

Будем работать с базой данных портала объявлений. В ней есть таблица ADS, содержащая данные о объявлениях, поданных за неделю.

Если вы хотите выполнить запросы к базе данных из этого урока на MS SQL Server, но эта СУБД не установлена на вашем компьютере, то ее можно установить, пользуясь инструкцией по этой ссылке .

А скрипт для создания базы данных "Портал объявлений 1", её таблицы и заполения таблицы данных - в файле по этой ссылке .

Для использующих же MySQL приводим содержание оператора CREATE для создания таблицы:

CREATE TABLE ADS ( Id INT (11) NOT NULL DEFAULT '100', Category varchar (25) DEFAULT 'Some Category', Part varchar (25) DEFAULT 'Some Part', Units INT (5) DEFAULT NULL , Money INT (10) DEFAULT NULL , PRIMARY KEY (Id) )

Пример 1. Итак, есть база данных портала объявлений. Таблица ADS выглядит так:

IdCategoryPartUnitsMoney
1ТранспортАвтомашины11017600
2НедвижимостьКвартиры8918690
3НедвижимостьДачи5711970
4ТранспортМотоциклы13120960
5СтройматериалыДоски687140
6ЭлектротехникаТелевизоры1278255
7ЭлектротехникаХолодильники1378905
8СтройматериалыРегипс11211760
9ДосугКниги966240
10НедвижимостьДома479870
11ДосугМузыка1177605
12ДосугИгры412665

Для вставки новой строки в эту таблицу на MySQL используем следующий запрос:

INSERT INTO ADS (Id, Category, Part, Units, Money) VALUES (13, 'Недвижимость', 'Гаражи', 22, 4620)

Или без указания имён столбцов:

INSERT INTO ADS VALUES (13, 'Недвижимость', 'Гаражи', 22, 4620) USE adportal1; INSERT INTO ADS (Category, Part, Units, Money) VALUES ('Недвижимость', 'Гаражи', 22, 4620);

В результате выполнения запроса в таблице появится новая строка:

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

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

Пример 2. Таким будет запрос на MySQL, в котором порядок следования столбцов изменён:

INSERT INTO ADS (Category, Id, Money, Part, Units) VALUES ('Недвижимость', 13, 4620, 'Гаражи', 22)

В результате выполнения запроса в таблице появится такая же новая строка, как и в примере 1.

Если вы используете MS SQL Server, то в запросе не нужно указывать столбец Id и запрос с изменённым порядком следования столбцов будет таким:

USE adportal1; INSERT INTO ADS (Category, Money, Part, Units) VALUES ('Недвижимость', 4620, 'Гаражи', 22)

Вставка значений по умолчанию (DEFAULT) и неопределённых значений (NULL)

Заметим, что при создании таблицы было предусмотрено, что значения столбцов могут иметь значения по умолчанию (DEFAULT). На MySQL для столбца Id можно предусмотреть значение 100. На MS SQL Server со строгим автоматическим приращением идентификатора это не допускается. В остальном же всё одинаково: для стобцов Category и Part значения по умолчанию - соответственно Some Category и Some Part, для столбцов Units и Money - значения NULL. Если в запросе на вставку данных на MySQL некоторые столбцы отсутствуют, то в них будут вставлены значения по умолчанию. На MS SQL в качестве значений нужно указать DEFAULT.

Пример 3. База данных и таблица - те же.

Запрос на MySQL. Вставим новые значения, указывая лишь столбец Id и его значение:

Все столбцы кроме Id получили значения по умолчанию. После выполнения этого запроса новая строка будет содержать следующие данные:

На MS SQL Server такой запрос недопустим.

Поскольку все столбцы могут иметь значения по умолчанию, можно использовать в запросе на вставку данных ключевое слово DEFAULT и не указывать имена столбцов.

Пример 4. Запрос на MySQL. Вставим новые значения, используя ключевое слово DEFAULT и не указывая имён столбцов:

INSERT INTO ADS VALUES ( DEFAULT , DEFAULT , DEFAULT , DEFAULT , DEFAULT )

Теперь все столбцы получили значения по умолчанию. После выполнения этого запроса новая строка будет содержать следующие данные:

Запрос на MS SQL Server (без указания столбца Id):

USE adportal1; INSERT INTO ADS VALUES ( DEFAULT , DEFAULT , DEFAULT , DEFAULT )

Вместо многократного использования слова DEFAULT можно использовать конструкцию DEFAULT VALUES, которая есть во многих диалектах SQL. Следует помнить, что в MySQL эта конструкция отсутствует.

Пример 5. Вставим новые значения, используя констукцию DEFAULT VALUES (запрос можно использовать и на MS SQL Server c предваряющей конструкцией USE adportal1):

После выполнения этого запроса новая строка будет содержать следующие данные:

Вставка значений с использованием оператора SET в MySQL

В MySQL дополнительно существует альтернативная конструкция для вставки значений в таблицу с использованием оператора SET. Она похожа на конструкцию оператора UPDATE и имеет следующий синтаксис:

INSERT INTO ИМЯ_ТАБЛИЦЫ SET ИМЯ_СТОЛБЦА_1=ЗНАЧЕНИЕ, ИМЯ_СТОЛБЦА_2=ЗНАЧЕНИЕ, . ИМЯ_СТОЛБЦА_N=ЗНАЧЕНИЕ

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

Пример 6. База данных и таблица - те же, что и в предыдущих примерах.

Вставим в таблицу строку, при этом столбцы Units и Money примут значения по умолчанию:

INSERT INTO ADS SET Category='Недвижимость', Part='Гаражи'

В результате выполнения запроса в таблице появится новая строка:

Использование механизма автоматического приращения при вставке данных

Механизм автоматического приращения предназначен для автоматического генерирования уникальных значений первичного ключа в таблице. При его использовании не требуется проверять все значения первичного ключа, чтобы определить максимальное значение. При создании новой записи можно указать в качестве значения первичного ключа 0 или NULL и в таблицу будет автоматически вставлено значение, увеличенное на единицу по сравнению с максимальным значением.

В разных диалектах SQL синтаксис автоматического приращения различается. В MySQL используется ключевое слово AUTO_INCREMENT. Таблица с использованием механизма AUTO_INCREMENT в MySQL создаётся так:

CREATE TABLE ADS ( Id INT (11) NOT NULL AUTO_INCREMENT , Category varchar (25) DEFAULT 'Some Category', Part varchar (25) DEFAULT 'Some Part', Units INT (5) DEFAULT NULL , Money INT (10) DEFAULT NULL , PRIMARY KEY (Id) )

В SQL Server используется ключевое слово IDENTITY (N, M), где N - начальное значение столца, M - шаг приращения. Так, указав IDENTITY (1, 1) мы обеспечим начальное значение первичного ключа 1 и приращение на 1 значения при каждой вставке новой строки:

CREATE TABLE ADS ( Id int IDENTITY (1, 1) PRIMARY KEY , Category varchar (25) DEFAULT 'Some Category', Part varchar (25) DEFAULT 'Some Part', Units INT (5) DEFAULT NULL , Money INT (10) DEFAULT NULL )

Вставка нескольких строк в таблицу

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

Для этого применяется либо однострочный, либо многострочный оператор INSERT. Рассмотрим сначала синтаксис однострочного варианта.

Пример 7. Если используется механизм автоматического приращения значений первичного ключа, то на MySQL вставить новые строки в таблицу можно, применив несколько раз оператор INSERT и указав в качестве значений первичного ключа 0 или NULL:

INSERT INTO ADS VALUES ( NULL , 'Электротехника', 'Телевизоры', 127, 8255); INSERT INTO ADS VALUES ( NULL , 'Электротехника', 'Холодильники', 137, 8905); INSERT INTO ADS VALUES ( NULL , 'Стройматериалы', 'Регипс', 112, 11760); INSERT INTO ADS VALUES ( NULL , 'Досуг', 'Книги', 96, 6240);

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

6ЭлектротехникаТелевизоры1278255
7ЭлектротехникаХолодильники1378905
8СтройматериалыРегипс11211760
9ДосугКниги966240

На MS SQL Server нет необходимости указывать значения столбца Id. Аналогичный запрос будет следующим:

USE adportal1; INSERT INTO ADS VALUES ('Электротехника', 'Телевизоры', 127, 8255); INSERT INTO ADS VALUES ('Электротехника', 'Холодильники', 137, 8905); INSERT INTO ADS VALUES ('Стройматериалы', 'Регипс', 112, 11760); INSERT INTO ADS VALUES ('Досуг', 'Книги', 96, 6240);

В MySQL и SQL Server существует многострочный оператор INSERT. Его отличие от однострочного варианта в том, что для вставки нескольких строк он используется один раз, а после ключевого слова VALUES указывается не один, а несколько списков значений добавляемых строк.

Пример 8. Вставим строки с теми же значениями, что и в предыдущем примере, используя многострочный оператор INSERT.

Запрос на MySQL:

INSERT INTO ADS VALUES ( NULL , 'Электротехника', 'Телевизоры', 127, 8255), ( NULL , 'Электротехника', 'Холодильники', 137, 8905), ( NULL , 'Стройматериалы', 'Регипс', 112, 11760), ( NULL , 'Досуг', 'Книги', 96, 6240);

Запрос на MS SQL Server:

USE adportal1; INSERT INTO ADS VALUES ('Электротехника', 'Телевизоры', 127, 8255), ('Электротехника', 'Холодильники', 137, 8905), ('Стройматериалы', 'Регипс', 112, 11760), ('Досуг', 'Книги', 96, 6240);

Результат применения - тот же, что и в предыдущем примере.

Примеры запросов к базе данных "Портал объявлений-1" есть также в уроках об операторах UPDATE, DELETE, HAVING и UNION.

Всем доброго времени суток.
Помогите пожалуйста.
Я использую Oracle9i. Создал следующую функцию:

Эта функция обрабатывает цены ценных бумаг и возвращает, но при этом должен был вставить другую запись в таблицу. в этом и вся проблема.

и вызываю эту функцию следующим образом:

ORA-14551: "невозможно выполнение операции DML внутри запроса"

Как решить проблему, подскажите. Но мне нужно, чтобы DML опреации проводились внутри функции и эту функцию объязательно вызывать в запросе как вышерасположенным образом. Иначе нельзя. Есть решение?
Спасибо.

__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь


Как передать в функцию два односвязных списка так, чтобы внутри функции можно было эти списки редактировать?
Мне нужно редактировать в функции два односвязных списка, как их передать в функцию, один.

Как быстро редактировать таблицу под стандартные настройки
Нужно напечатать очень много страниц с книги с множеством данных и цифр, сначала я печатал, но.

Как редактировать таблицу из кода или сделать привязку?
Доброго дня! Вопрос в следующем: Делаю приложение, которое готовит печатную форму. Где всё без.

Как сделать чтобы можно было редактировать таблицу через DataGridView?
Заполняю таблицу таким способом. dataGridView1.ColumnHeadersDefaultCellStyle.Font = new.

Откуда Вы собрались вызывать функцию?

Из запроса? - Нельзя. Запрос придётся переписать в pl/sql.

Какой резон совмещать в одном блоке два действия (поиск цены и добавление имени акции)? Ответ на этот вопрос решит проблему.

Сделайте функцию процедурой или перенесите в пакет, задав правильно PRAGMA. Первое проще.

Технически реализовать вашу идею можно следующим образом:
На практике полностью соглашусь с Laba в том что так писать не нужно. Трижды подумайте перед тем как вводить подобный код в промышленную эксплуатацию. Я бы за это отрывал руки.

О! Я думал прагму можно только в пакете писать.

Из запроса? - Нельзя. Запрос придётся переписать в pl/sql. да ну ладно, я юзаю функции из запросов нормально. процедуры нельзя, это уж точно.

Ну я тоже не раз вызывал функции из запросов. Но в этом случае возникла ошибка. Как я уже понял нужно использовать прагмы. я попробую реализовать в свой проект код DLINNBLY. Если все успешно, то сообщу вам.

Для чего мне понадобился такой код? Использовать DML операцию внутри функции, которая вызывается из sql запросах.
Я создаю отчет на CrystalReports XI. И в отчете использую параметр множественного выбора, т.е. значение multiple values = true. В 11 версии кристалла не возможно использовать подобный параметр в sql запросах. Например, в кристалле пишется обычный sql запрос:

Читайте также: