Sql-запросы в firebird. примеры select, insert, update, delete для firebird

Выборка SELECT из базы данных FIREBIRD

Выборка из базы данных — это основная часть нашей работы. Без запросов в базу данных нельзя сделать полноценный динамический сайт. Запрос к одной таблице — это простая задача, а вот запрос к нескольким таблицам — сложная задача. Тут легко запутаться. Очень важно научиться вытаскивать массив значений из базы данных Firebird по определённому запросу.

#Поиск записей о продажах, для которых не установлена дата отгрузки:
SELECT *
FROM SALES
WHERE SHIP_DATE IS NULL;

Как это не странно, но NULL — тоже значение. Вы можете использовать поиск по нему. При записи в базу данных важно учитывать какое поле может быть пустым, а какое должно быть с определённым значением.

#Найти тех сотрудников, у которых нет проектов
SELECT *
FROM employee
WHERE NOT EXISTS(SELECT * FROM employee_project ep WHERE ep.emp_no = employee.emp_no)

Очень удобно использовать подзапрос IN. Вы могли бы через запятую перечислить значения, но это приведёт к тому, что запрос будет статичным и вам каждый раз придётся его менять. К тому же число значений в подзапросе может быть достаточно большим.

В этом случае длина SQL-запроса может быть довольно большой. Если вам нужно передать массив PHP в подзапрос IN, то перейдите на страницу Как превратить массив в строку для оператора IN() PHP. Массив будет превращён в строку.

Например, строка с id: '1,2,3,4,5,6,7'

#IN(подзапрос)
SELECT *
FROM SHOP
WHERE SHOP_ID IN(SELECT SHOP_ID FROM SHOP WHERE SHOP_ID >1 AND SHOP_ID < 6); #NOT IN(подзапрос) если не соответствует SELECT * FROM SHOP WHERE SHOP_ID NOT IN(SELECT SHOP_ID FROM SHOP WHERE SHOP_ID >1 AND SHOP_ID < 6); #выборка по нескольким значениям одного поля SELECT * FROM SHOP WHERE SHOP_ID NOT IN(1,2,3);

Подзапросы хороши тем, что вам не нужно делать несколько запросов, а потом работать с массивами. Вы облегчите себе труд. Будет минимум писанины.

#EXISTS(подзапрос)
SELECT *
FROM SHOP
WHERE EXISTS(SELECT SHOP_ID FROM SHOP WHERE SHOP_ID >1 AND SHOP_ID < 6); #ALL Вывести только тех заказчиков, чьи оценки выше, #чем у каждого заказчика в Париже SELECT * FROM Customers WHERE rating > ALL (SELECT rating FROM Customers WHERE city = 'Paris')

В Firebird нет Limit как в MySQL. Тут нужно использовать FIRST.

#FIRST первые 2
SELECT FIRST 2 SHOP_ID FROM SHOP
#SKIP — последующие
SELECT SKIP 2 SHOP_ID FROM SHOP

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

#FIRST (SELECT только в скобках)
DELETE FROM MYTABLE
WHERE ID IN (SELECT FIRST 10 ID FROM MYTABLE)
#последние 2 записи
SELECT skip ((select count(*) — 2 from SHOP)) SHOP_NAME, SHOP_ID FROM SHOP
#Этот запрос вернет строки 81-100 из таблицы PEOPLE:
select first 20 skip 80 id, name from People
order by name asc

Очень часто нужно увидеть на экране уникальные значения. Тут без DISTINCT не обойтись. DISTINCT является неким фильтром, который удаляет повторяющиеся значения.

#без повторов
SELECT DISTINCT SHOP_NAME FROM SHOP
#группировка
SELECT SHOP_NAME FROM SHOP GROUP BY SHOP_NAME
#магазин + группировка + Большие буквы
SELECT 'магазин ' || upper(SHOP_NAME) FROM SHOP GROUP BY SHOP_NAME

Удобно использовать маленькое начертание букв при помощи lower. Вы можете использовать php-функцию mb_strtolower(). Её часто придется применять, что не очень удобно.

#условие + приведение к маленькому регистру
select case lower(SHOP_NAME) when 'майкоп' then 'Майкоп::2015' when 'ростов' then 'Ростов::2015' else '-нет-'
end as title,
SHOP_ID
from SHOP
# left join
select *
from A
left [outer] join B on A.id = B.code

Вязание таблиц между собой — это самый сложный этап работы. Я часто ломаю голову и редко пишу сложный SQL-запрос без ошибок. Тут вам придется собраться и набраться терпения. Ошибка в один символ приведёт к ошибке в запросе. Вы должны будите привязать таблицы по параметрам. Чаще всего вяжут таблицы по ID.

#выборка
select * from flotsam f
join jetsam j on f.sea = j.sea
and f.ship = j.ship
#или
select * from flotsam
join jetsam using (sea, ship)
# Перестроим наши ранние примеры. Мы можем использовать предложение # HAVING для исключения малых групп студентов:
select class, count(*) as num_boys, avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having count(*) >= 5
#Выберем только группы, которые имеют минимальный разброс по возрасту #1,2 года
select class, count(*) as num_boys, avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having max(age) — min(age) > 1.2

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

#максимальные и минимальные значения
SELECT mix(SHOP_ID) FROM SHOP
SELECT max(SHOP_ID) FROM SHOP
#среднее значение
SELECT avg(SHOP_ID) FROM SHOP

Иногда нужно объединять несколько таблиц. Помните, что количество полей должно совпадать как по количеству, так и по типу. Если не получается объединить выборку из 2 таблиц, то применить union all.

#Этот запрос представляет информацию из различных музыкальных #коллекций в одном наборе данных с помощью объединений:
select id, title, artist, length, 'CD' as medium
from cds
union
select id, title, artist, length, 'LP'
from records
union
select id, title, artist, length, 'MC'
from cassettes
order by 3, 2 — artist, title

просмотры: 7144, уровень: лёгкий уровень, рейтинг: 3, дата: 2015-08-04 23:00:00

Источник: http://trainingweb.ru/page/select-firebird

SQL INSERT, UPDATE, DELETE — вставка, изменение и удаление данных

Операторы SQL INSERT, UPDATE и DELETE предназначены соответственно для вставки, изменения и удаления данных из таблиц баз данных.

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

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

Можно писать этот запрос и без имён столбцов:

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

Пример 1. Есть база портала объявлений. В ней есть таблица Ads, содержащая данные о объявлениях, поданных за неделю (более подробно — в уроке об агрегатных функциях SQL, пример 7). Таблица выглядит так:

Id Category Part Units Money
1 Транспорт Автомашины 110 17600
2 Недвижимость Квартиры 89 18690
3 Недвижимость Дачи 57 11970
4 Транспорт Мотоциклы 131 20960
5 Стройматериалы Доски 68 7140
6 Электротехника Телевизоры 127 8255
7 Электротехника Холодильники 137 8905
8 Стройматериалы Регипс 112 11760
9 Досуг Книги 96 6240
10 Недвижимость Дома 47 9870
11 Досуг Музыка 117 7605
12 Досуг Игры 41 2665

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

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

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

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

Читайте также:  Компьютер выключается сам по себе. компьютер включается и сразу выключается

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

13 Недвижимость Гаражи 22 4620

Оператор SQL UPDATE предназначен для обновления (редактирования) данных в таблице. Он применяется, когда в той или иной строке таблицы уже записаны некоторые данные и нужно внести в них изменения. Оператор UPDATE имеет следующий синтаксис:

UPDATE ИМЯ_ТАБЛИЦЫ SET ИМЯ_СТОЛБЦА_1=ЗНАЧЕНИЕ, …, ИМЯ_СТОЛБЦА_N=ЗНАЧЕНИЕ WHERE УСЛОВИЕ

Пример 2. База данных и таблица — те же, что и в примере 1.

Требуется изменить значения столбцов Units и Money в строке с ID=4. Для этого пишем следующий запрос:

UPDATE ADS SET Units=148, Money=23680 WHERE ID=4

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

4 Транспорт Мотоциклы 148 23680

Оператор SQL DELETE предназначен для удаления данных из таблицы. Он имеет следующий синтаксис:

DELETE FROM ИМЯ_ТАБЛИЦЫ WHERE УСЛОВИЕ

Если не указывать условие, из таблицы будут удалены все строки. Кроме того, следует помнить, что могут быть удалены лишь строки с первичными ключами, на которые не ссылаются внешние ключи в других таблицах (более подробно об ограничениях удаления — в уроке Реляционная модель данных).

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

Требуется удалить из таблицы строку, имеющую идентификатор 4. Для этого пишем следующий запрос:

DELETE FROM ADS WHERE ID=4

Поделиться с друзьями

Другие темы в блоке «Реляционные базы данных»

Реляционная модель данныхОсновы проектирования базы данных — примерSQL ALTER TABLE — изменение таблицы базы данныхSQL SELECT — запрос на выборку данныхSQL JOIN — соединение таблиц базы данныхSQL HAVING — получение данных с интересующими значениямиSQL UNION — объединение результатов запросов

Источник: https://function-x.ru/sql_insert_update_delete.html

SQL | Инструкция INSERT INTO

Инструкция SQL INSERT INTO и INSERT SELECT используются для вставки новых строк в таблицу. Существует два способа использования инструкций:

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

Синтаксис:

INSERT INTO имя_таблицы VALUES (значение1, значение2, значение3,…); имя_таблицы: имя таблицы. значение1, значение2,.. : значения первого столбца, второго столбца,… для новой записи

  1. Имена столбцов и значения: При втором методе указываются имена столбцов и значения строк для вставки:

Синтаксис:

INSERT INTO имя_таблицы (столбец1, столбец2, столбец3,..) VALUES (значение1, значение2, значение3,…); имя_таблицы: имя таблицы. столбец1: имя первого столбцы, второго столбца … значение1, значение2,.. : значения первого столбца, второго столбца,… для новой записи

Запросы:

Способ 1 (вставка только значений):

INSERT INTO Student VALUES ('5','HARSH','WEST BENGAL','8759770477','19');

Результат:

После использования INSERT INTO SELECT таблица Student теперь будет выглядеть следующим образом:

ROLL_NO NAME ADDRESS PHONE Age
1 Ram Delhi 9455123451 18
2 RAMESH GURGAON 9562431543 18
3 SUJIT ROHTAK 9156253131 20
4 SURESH Delhi 9156768971 18
3 SUJIT ROHTAK 9156253131 20
2 RAMESH GURGAON 9562431543 18
5 HARSH WEST BENGAL 8759770477 19

Способ 2 (вставка значений только в указанные столбцы):

INSERT INTO Student (ROLL_NO, NAME, Age) VALUES ('5','PRATIK','19');

Результат:

Таблица Student теперь будет выглядеть следующим образом:

ROLL_NO NAME ADDRESS PHONE Age
1 Ram Delhi 9455123451 18
2 RAMESH GURGAON 9562431543 18
3 SUJIT ROHTAK 9156253131 20
4 SURESH Delhi 9156768971 18
3 SUJIT ROHTAK 9156253131 20
2 RAMESH GURGAON 9562431543 18
5 PRATIK null null 19

Обратите внимание, что для столбцов, значения для которых не указаны, задается null.

Использование SELECT в инструкции INSERT INTO

Можно использовать инструкцию MySQL INSERT SELECT для копирования строк из одной таблицы и их вставки в другую.

Использование этого оператора аналогично использованию INSERT INTO. Разница в том, что оператор SELECT применяется для выборки данных из другой таблицы. Ниже приведены различные способы использования INSERT INTO SELECT:

  • Вставка всех столбцов таблицы: можно скопировать все данные таблицы и вставить их в другую таблицу.

Синтаксис:

INSERT INTO первая_таблица SELECT * FROM вторая_таблица; первая_таблица: имя первой таблицы. вторая_таблица: имя второй таблицы.

Мы использовали инструкцию SELECT для копирования данных из одной таблицы и инструкцию INSERT INTO для их вставки в другую.

  • Вставка отдельных столбцов таблицы. Можно скопировать только те столбцы таблицы, которые необходимо вставить в другую таблицу.

Синтаксис:

INSERT INTO первая_таблица(имена_столбцов1) SELECT имена_столбцов2 FROM вторая_таблица; первая_таблица: имя первой таблицы. вторая_таблица: имя второй таблицы. имена_столбцов1: имена столбцов, разделенные запятой(,) для таблицы 1. имена_столбцов2: имена столбцов, разделенные запятой(,) для таблицы 2.

Мы использовали инструкцию SELECT для копирования данных только из выбранных столбцов второй таблицы и инструкцию MySQL INSERT INTO SELECT для их вставки в первую таблицу.

  • Копирование определенных строк из таблицы. Можно скопировать определенные строки из таблицы для последующей вставки в другую таблицу с помощью условия WHERE с оператором SELECT. В этом случае нужно использовать соответствующее условие в WHERE.

Синтаксис:

INSERT INTO таблица1 SELECT * FROM таблица2 WHERE условие; таблица1: имя первой таблицы. таблица2: имя второй таблицы. условие: условие для выбора строк.

Таблица 2: LateralStudent

ROLL_NO NAME ADDRESS PHONE Age
7 SOUVIK DUMDUM 9876543210 18
8 NIRAJ NOIDA 9786543210 19
9 SOMESH ROHTAK 9687543210 20

Запросы:

Способ 1 (вставка всех строк и столбцов):

INSERT INTO Student SELECT * FROM LateralStudent;

Результат:

Этот запрос вставит все данные таблицы LateralStudent в таблицу Student. После применения SQL INSERT INTO SELECT таблица Student будет выглядеть следующим образом:

ROLL_NO NAME ADDRESS PHONE Age
1 Ram Delhi 9455123451 18
2 RAMESH GURGAON 9562431543 18
3 SUJIT ROHTAK 9156253131 20
4 SURESH Delhi 9156768971 18
3 SUJIT ROHTAK 9156253131 20
2 RAMESH GURGAON 9562431543 18
7 SOUVIK DUMDUM 9876543210 18
8 NIRAJ NOIDA 9786543210 19
9 SOMESH ROHTAK 9687543210 20

Способ 2 (вставка отдельных столбцов):

INSERT INTO Student(ROLL_NO,NAME,Age) SELECT ROLL_NO, NAME, Age FROM LateralStudent;

Результат:

Этот запрос вставит данные из столбцов ROLL_NO, NAME и Age таблицы LateralStudent в таблицу Student. Для остальных столбцов таблицы Student будет задано значение null. После применения SQL INSERT SELECT таблица будет выглядеть следующим образом:

ROLL_NO NAME ADDRESS PHONE Age
1 Ram Delhi 9455123451 18
2 RAMESH GURGAON 9562431543 18
3 SUJIT ROHTAK 9156253131 20
4 SURESH Delhi 9156768971 18
3 SUJIT ROHTAK 9156253131 20
2 RAMESH GURGAON 9562431543 18
7 SOUVIK Null null 18
8 NIRAJ Null null 19
9 SOMESH Null null 20
  • Выбор определенных строк для вставки:

INSERT INTO Student SELECT * FROM LateralStudent WHERE Age = 18;

Результат:

Этот запрос выберет только первую строку из таблицы LateralStudent для вставки в таблицу Student. После применения INSERT SELECT таблица будет выглядеть следующим образом:

ROLL_NO NAME ADDRESS PHONE Age
1 Ram Delhi 9455123451 18
2 RAMESH GURGAON 9562431543 18
3 SUJIT ROHTAK 9156253131 20
4 SURESH Delhi 9156768971 18
3 SUJIT ROHTAK 9156253131 20
2 RAMESH GURGAON 9562431543 18
7 SOUVIK DUMDUM 9876543210 18

Перевод статьи «SQL INSERT INTO Statement» дружной командой проекта Сайтостроение от А до Я.

Источник: https://www.internet-technologies.ru/articles/sql-instrukciya-insert-into.html

SQL для генерации описания структуры таблиц Firebird 2.x

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

Но иногда приходится решать противоположную задачу: на руках у разработчика есть база данных, к которой документация отсутствует (например, доставшаяся «по наследству» от менее организованных предшественников), или к ней по каким-то причинам нет доступа.

Читайте также:  Виртуализация серверов с применением microsoft hyper-v

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

Разумеется, если вы ежедневно пользуетесь программами типа DBSchema или им подобными (или хотя бы встроенной подпрограммой генерации документации из IBExpert), то ничего изобретать не нужно: они уже умеют это делать. Если же нужно просто быстро получить в читаемом виде описание структуры десятка таблиц базы и нет под рукой никаких нужных программ (или результаты их работы не устраивают, или — почему бы и нет? — вы самостоятельно пишете такую систему), то можно воспользоваться SQL-запросом, который извлекает всю нужную информацию прямо из метаданных базы.Мы хотим написать SQL-запрос, получающий на вход список таблиц базы данных, разделённых запятыми (или как-то ещё), а на выходе предоставляющий нам отформатированный определённым образом текст, который включает: названия и описания таблиц, а также список полей с указанием для каждого из них:

  • типа,
  • особенностей (первичный ключ, уникальное, ссылочный ключ),
  • имени таблицы и поля в ней, на которые данное поле ссылается,
  • описания.

Выходной текст потом можно без существенных правок загрузить в какую-нибудь программу (я использую форматы CSV для Excel и HTML, но ниже рассказывается и о других применениях).

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

Требования

Запрос тестировался под Firebird 2.5. Скорее всего, он также будет работать и под управлением Firebird 2.1. Наверняка не будет под Firebird 1.x. По поводу СУБД версии 3.x ничего пока сказать не могу.

Параметры

Запрос принимает на вход:

  • список таблиц,
  • разделитель к этому списку (например, это может быть запятая или перевод строки),
  • подстановку для замены перевода строки (например, в HTML вместо перевода строки нужно писать
    , а в Excel — символ «line feed» с кодом 10),
  • две строки формата: для таблицы и для поля,
  • необязательную строку для «подножия» таблицы (в HTML это

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

На выходе — строка varchar(10000) вместо blob, чтобы не нужно было производить никакие специальные действия при чтении строки сторонними программами (например, если вставить вызов этого запроса в программу на PHP для получения информации о базе через web, то для чтения blob-полей придётся писать специальный код, а varchar читается «как есть»). Число 10000 взято наобум, если этого будет мало, то можно добавить.

Источник: http://mik-demidov.blogspot.com/2015/07/firebird-sql-docs-maker.html

INSERT SELECT в Firebird

Я не понимаю, зачем вам нужен спусковой крючок.

Эта проблема:

Может быть решена с помощью одной инструкции insert … select .

insert into material (id, location, posid, artid, quantity) select next value for seq_mat_id, 1000, next value for seq_pos, id, 1 from bas_art where artcategory = 'My Word';

Это предполагает, что существует вторая последовательность (она же «генератор»), которая называется seq_mat_id которая предоставляет новый идентификатор для столбца material.id

Для большей части моего ответа я возьму очень простую таблицу:

CREATE TABLE MyTable ( ID BIGINT PRIMARY KEY, SomeValue VARCHAR(255), posid INTEGER )

Идентификатор автоинкремента

Firebird (до версии 2.5) не имеет типа столбца идентификатора (он будет добавлен в Firebird 3), вместо этого вам нужно использовать последовательность (aka generator) и триггер, чтобы получить это.

Последовательность

Сначала вам нужно создать последовательность, используя CREATE SEQUENCE :

CREATE SEQUENCE seqMyTable

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

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

Вызывать

Чтобы сгенерировать значение для идентификатора автоматического инкремента, вам необходимо использовать BEFORE INSERT TRIGGER который присваивает сгенерированное значение столбцу – в этом примере – ID .

CREATE TRIGGER trgMyTableAutoIncrement FOR MyTable ACTIVE BEFORE INSERT POSITION 0 AS BEGIN NEW.ID = NEXT VALUE FOR seqMyTable; END

В этом примере я всегда назначаю сгенерированное значение, другие примеры присваивают сгенерированное значение только тогда, когда ID равен NULL .

Получение значения

Чтобы получить сгенерированное значение, вы можете использовать RETURNING -clause для INSERT state:

INSERT INTO MyTable (SomeValue) VALUES ('abc') RETURNING ID

INSERT INTO … SELECT

Используя INSERT INTO … SELECT вы можете выбирать строки из одной таблицы и вставлять их в другие. Причина, по которой он не работает для вас, заключается в том, что вы пытаетесь присвоить строковое значение ':pos' столбцу типа INTEGER , и это недопустимо.

Предполагая, что у меня есть другая таблица MyOtherTable с аналогичной структурой, такой как MyTable я могу передавать значения, используя:

INSERT INTO MyTable (SomeValue) SELECT SomeOtherValue FROM MyOtherTable

Использование INSERT INTO … SELECT невозможно получить сгенерированные значения, если только одна строка не была вставлена.

Догадки в отношении POSID

Мне непонятно, что такое POSID и какие ценности он должен иметь. Похоже, вы хотите увеличить значение начиная с 1 для одного INSERT INTO … SELECT . В версиях Firebird до 2.5 это невозможно (в Firebird 3 вы можете использовать ROW_NUMBER() для этого).

Если моя догадка правильная, тогда вам нужно будет использовать EXECUTE BLOCK (или хранимую процедуру) для назначения и увеличения значения для каждой строки, которую нужно вставить.

Блок выполнения будет выглядеть примерно так:

EXECUTE BLOCK AS DECLARE posid INTEGER = 1; DECLARE someothervalue VARCHAR(255); BEGIN FOR SELECT SomeOtherValue FROM MyOtherTable INTO :someothervalue DO BEGIN INSERT INTO MyTable (SomeValue, posid) VALUES (:someothervalue, :posid); posid = posid + 1; END END

Без ORDER BY с SELECT значение posid по сути бессмысленно, потому что нет гарантированного порядка.

Источник: http://sql.fliplinux.com/insert-select-firebird.html

INSERT SELECT в Firebird

Для большей части моего ответа я возьму очень простую таблицу:

CREATE TABLE MyTable ( ID BIGINT PRIMARY KEY, SomeValue VARCHAR(255), posid INTEGER
)

Идентификатор автоинкремента

Firebird (до версии 2.5) не имеет типа столбца идентификатора (он будет добавлен в Firebird 3), вместо этого вам нужно использовать последовательность (aka generator) и триггер, чтобы получить это.

Последовательность

Сначала вам нужно создать последовательность, используя CREATE SEQUENCE:

CREATE SEQUENCE seqMyTable

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

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

Вызывать

Чтобы сгенерировать значение для идентификатора автоматического инкремента, вам необходимо использовать BEFORE INSERT TRIGGER который присваивает сгенерированное значение столбцу — в этом примере — ID.

CREATE TRIGGER trgMyTableAutoIncrement FOR MyTable
ACTIVE BEFORE INSERT POSITION 0
AS BEGIN NEW.ID = NEXT VALUE FOR seqMyTable;
END

В этом примере я всегда назначаю сгенерированное значение, другие примеры присваивают сгенерированное значение только тогда, когда ID равен NULL.

Получение значения

Чтобы получить сгенерированное значение, которое вы можете использовать RETURNING -clause в INSERT -statement:

INSERT INTO MyTable (SomeValue) VALUES ('abc') RETURNING ID

INSERT INTO… SELECT

Используя INSERT INTO… SELECT вы можете выбирать строки из одной таблицы и вставлять их в другие. Причина, по которой он не работает для вас, заключается в том, что вы пытаетесь присвоить строковое значение ':pos' столбцу типа INTEGER, и это недопустимо.

Предполагая, что у меня есть другая таблица MyOtherTable с аналогичной структурой, такой как MyTable я могу передавать значения, используя:

INSERT INTO MyTable (SomeValue) SELECT SomeOtherValue FROM MyOtherTable

Использование INSERT INTO… SELECT невозможно получить сгенерированные значения, если только одна строка не была вставлена.

Догадки в отношении POSID

Мне непонятно, что такое POSID и какие ценности он должен иметь. Похоже, вы хотите увеличить значение начиная с 1 для одного INSERT INTO… SELECT. В версиях Firebird до 2.5 это невозможно (в Firebird 3 вы можете использовать ROW_NUMBER() для этого).

Если моя догадка правильная, тогда вам нужно будет использовать EXECUTE BLOCK (или хранимую процедуру) для назначения и увеличения значения для каждой строки, которую нужно вставить.

Блок выполнения будет выглядеть примерно так:

EXECUTE BLOCK
AS DECLARE posid INTEGER = 1; DECLARE someothervalue VARCHAR(255);
BEGIN FOR SELECT SomeOtherValue FROM MyOtherTable INTO :someothervalue DO BEGIN INSERT INTO MyTable (SomeValue, posid) VALUES (:someothervalue, :posid); posid = posid + 1; END
END

Без ORDER BY с SELECT значение posid по сути бессмысленно, потому что нет гарантированного порядка.

Источник: http://qaru.site/questions/7865453/insert-select-in-firebird

MS SQL Server + FireBird = Дружба

Александр Чмиль
дата публикации

Версия для печати

Недавно столкнулся с проблемой, когда данные из базы данных FireBird (F) нужно было импортировать в базу данных MS SQL Server 2000 (S). Первой мыслью было написать клиента, который бы подключался одновременно к двум БД и в цикле переносил данные из всех таблиц одной базы в другую.

Данный подход мне сразу не понравился тем, что пришлось бы писать на Delphi отдельную процедуру импорта данных под каждую таблицу БД — структура и типы данных у них ведь разные. Кроме того, типы данных у этих БД несколько «не стыкуются», так что пришлось бы учитывать и эту особенность при переносе данных.

За советом я обратился к специалистам на Круглом столе Королевства Delphi — вопрос № 71949. Достопочтенный Green в первом же ответе направил меня совершенно в другом направлении: не клиента писать, а подружить эти две СУБД. Полученный результат настолько меня впечатлил, что я решил написать данную статью.

Итак, для того, чтобы иметь возможность делать запросы из (S) к (F), в первую очередь необходимо установить OLE-провайдер, обеспечивающего связь с БД (F). Поиск в Интернете привел на сайт http://www.ibprovider.

com, с которого можно скачать бесплатную версию IBProvider.

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

Следующим шагом будет регистрация IBProvider в системе. Копируем файлы _IBProvider_v3_free_i.dll и cc3250mt.dll в системную папку Windows (например, в c:windowssystem32) и в командной строке выполняем команду:

regsvr32 _IBProvider_v3_free_i.dll

В результате в списке провайдеров появится LCPI.IBProvider.3.Free.

Хочу заметить, что для «дружбы» (S) с (F) в системе должна быть запущена служба MSDTC (Distributed Transaction Coordinator или Координатор Распределенных Транзакций). В моем случае данная служба была отключена и в упорно не желала запускаться (MS Windows 2000). Поиск в Интернете привел к следующему трюку в командной строке:

net stop msdtc net start msdtc

При наличии прав администратора в списке служб находим «Координатор распределенных транзакций» и устанавливаем тип запуска «авто».

Все. Теперь мы можем работать с БД (F) как из скрипта MS SQL Server, так и через TADOConnection в Delphi, указав в качестве провайдера LCPI.IBProvider.3.Free. Вот пример содержимого строки ADOConnection.ConnectionString:

Provider=LCPI.IBProvider.3.Free;Password=пароль_к_БД;Persist Security Info=True;User ID=логин_к_БД; Location=D:ProjectsdbDB.FDB;ctype=ASCII;dialect=3;auto_commit=False; support_odbc_query=False;unicode_mode=False;unicode_stmt=False;dbclient_library=gds32.dll; dbclient_type=fb

Вернусь к своей задаче — импорт данных в БД MS SQL Server из БД FireBird. Создаем БД (S) по структуре идентичную БД (F). Из-за различий в типах данных этих двух СУБД, в БД (S) создаем столбцы в соответствии с таблицей приведения типов:

Типы данных (F) Типы данных (S)
timestamp datetime
varchar nvarchar
float float или money
smallint (в роли boolean) bit
blob image

Не буду расписывать все соответствия. Их Вы можете определить экспериментально или найти информацию в Интернете.

Перейдем к самому интересному — к «дружбе народов» :

Для получения набора данных из внешней БД, в СУБД (S) имеется функция OpenRowSet, синтаксис которой выглядит так:

( , { ; ; | } , { [ catalog. ] [ schema. ] object | } )

Описание функции Вы можете найти в Transact-SQL Reference. В нашем случае эта функция используется с таким набором параметров:

OpenRowSet (, , )

В качестве первого параметра указывается имя провайдера (LCPI.IBProvider.3.Free), в качестве второго — строка соединения с БД FireBird, третьего — запрос на выборку данных (select * from TableName).

Для импортирования данных на (S) создаем две ХП:

ImportFBTable @Table nvarchar(30) exec(+@Table) exec(+@Table++ + + + + ) ImportFBData exec ImportFBTable exec ImportFBTable exec ImportFBTable … exec ImportFBTable

Выполняем процедуру ImportFBData, которая поочередно вызывает процедуру ImportFBTable, передавая ей в качестве параметра имя импортируемой таблицы (естественно, имена таблиц в (F) и (S) должны быть одинаковыми).

Процедура ImportFBTable очищает данные в таблице на (S), получает набор данных из таблицы на (F) и вносит их в таблицу на (S).

Конечно, при желании можно «заставить» процедуру не удалять данные, а обновлять, но предоставляю Вам самим создать сие действо — в рамках моей задачи это было не обязательно, так как я не использовал в таблицах на (S) внешние индексы.

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

В заключении хотел сказать, что таким образом можно «подружить» MS SQL Server и с другими БД при наличии соответствующего OLE-провайдера. Например, вот тут вопрос № 71737 рассказывается, как можно получить данные с листа MS Excel.

Также хочу выразить огромную благодарность г-ну Александру Зеленову (aka Green), вовремя направившего меня «на путь истинный» и вдохновившего к написанию данной статьи.

[MS SQL Server] [Гетерогенные запросы] [FireBird & Yafill]

 Обсуждение материала [ ] 5 сообщений

Источник: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1412

Ссылка на основную публикацию