Postgres получение предполагемого id
Вопрос нафига? Вот вы положим узнали следующее значение. А пока узнавали кто-то рядом взял и вставил туда запись. И что вы теперь с этим знанием делать?
21 июл 2015 в 20:05
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Обращаю внимание, это не предполагаемое id , это число, которое можно использовать в качестве id (не id !). Фактически вставленное id можно получить, вызвав
SELECT currval('myshema.tbl_item_id_seq')
в той же сессии после операции insert .
Последовательности гарантируют получение разных чисел — в одной транзакции, или в параллельных, неважно. Числа могут повторяться только когда последовательность начнёт следующий цикл или произойдёт её сброс.
Если вы вызвали
SELECT nextval('myshema.tbl_item_id_seq')
INSERT INTO myshema.tbl_item(data. more_fields) VALUES('any_data'. 'any data n');
если поле задавалось как
SERIAL\BIGSERIAL id , полученный первой функцией не совпадёт с id фактически вставленной записи.
И надо обязательно указывать
INSERT INTO myshema.tbl_item(id,data. more_fields) VALUES('результат предыдущего вызова nextval', 'any_data'. 'any data n');
Получение id добавленной записи в PostgeSQL
Каким бы супер-пупер спецом вы не были — в процессе разработки эпизодически попадаются интересные и удобные вещи о которых, казалось бы, давно бы пора знать, но все никак не складывалось. Этакий ништячок, найдя который хочется воскликнуть: «Эврика!». Вот таким ништячком для меня стал элемент синтаксиса INSERT в PostgreSQL, которым я и хочу поделиться с вами.
Ситуация: После добавления записи в базу нужно получить id этой самой свеже-вставленной записи.
Решение на PostgreSQL: INSERT… RETURNING id где id — это PRIMARY_KEY в таблице.
Просто и элегантно, не правда ли?
Подробный пример:
postgres=# create table test (id serial,name text);
NOTICE: CREATE TABLE will create implicit sequence «test_id_seq» for serial column «test.id»
CREATE TABLE
postgres=# INSERT INTO test (name) VALUES (‘My Name’) RETURNING id;
id
—-
1
postgres=# INSERT INTO test (name) VALUES (‘My Name 1’) RETURNING id;
id
—-
2
(1 row)
- postrgres
- postgreSQL
- last insert id
Get id from INSERT or SELECT
I’ve this function that inserts a row into a city table without duplicates. It returns the id of the inserted row:
CREATE OR REPLACE FUNCTION public.insert_city( character varying, character varying, character varying, character varying, character varying, character varying) RETURNS integer AS $BODY$ DECLARE name_city1 ALIAS FOR $1; country1 ALIAS FOR $2; province1 ALIAS FOR $3; region1 ALIAS FOR $4; cap1 ALIAS FOR $5; nationality1 ALIAS FOR $6; id_city1 integer; BEGIN INSERT INTO city (name_city, country, province, region, cap, nationality) SELECT name_city1, country1, province1, region1, cap1, nationality1 WHERE NOT EXISTS (SELECT id_city FROM city WHERE name_city = name_city1) RETURNING id_city INTO id_city1; -- xxx END; $BODY$ LANGUAGE plpgsql VOLATILE;
xxx marks the spot where I need something like this:
IF is_number(id_city1) THEN RETURN id_city1; ELSE RETURN query select id_city from city where name_city=name_city1; END IF;
If the first query does not insert a new row and I don’t get an id_city from it, I want to execute the second query to select an existing id_city . How can I do this?
Операции с данными
Для добавления данных применяется команда INSERT , которая имеет следующий формальный синтаксис:
INSERT INTO имя_таблицы (столбец1, столбец2, . столбецN) VALUES (значение1, значение2, . значениеN)
После INSERT INTO идет имя таблицы, затем в скобках указываются все столбцы через запятую, в которые надо добавлять данные. И в конце после слова VALUES в скобках перечисляются добавляемые значения.
Допустим, у нас в базе данных есть следующая таблица:
CREATE TABLE Products ( Id SERIAL PRIMARY KEY, ProductName VARCHAR(30) NOT NULL, Manufacturer VARCHAR(20) NOT NULL, ProductCount INTEGER DEFAULT 0, Price NUMERIC );
Добавим в нее одну строку с помощью команды INSERT:
INSERT INTO Products VALUES (1, 'Galaxy S9', 'Samsung', 4, 63000)
После удачного выполнения в pgAdmin в поле сообщений должно появиться сообщение «INSERT 0 1»:
Стоит учитывать, что значения для столбцов в скобках после ключевого слова VALUES передаются по порядку их объявления. Например, в выражении CREATE TABLE выше можно увидеть, что первым столбцом идет Id, поэтому этому столбцу передаетсячисло 1. Второй столбец называется ProductName, поэтому второе значение — строка «Galaxy S9» будет передано именно этому столбцу и так далее. То есть значения передаются столбцам следующим образом:
- Id: 1
- ProductName: ‘Galaxy S9’
- Manufacturer: ‘Samsung’
- ProductCount: 4
- Price: 63000
Также при вводе значений можно указать непосредственные столбцы, в которые будут добавляться значения:
INSERT INTO Products (ProductName, Price, Manufacturer) VALUES ('iPhone X', 71000, 'Apple');
Здесь значение указывается только для трех столбцов. Причем теперь значения передаются в порядке следования столбцов:
- ProductName: ‘iPhone X’
- Manufacturer: ‘Apple’
- Price: 71000
Для столбца Id значение будет генерироваться автоматически базой данных, так как он представляет тип Serial. То есть к значению из последней строки будет добавляться единица.
Для остальных столбцов будет добавляться значение по умолчанию, если задан атрибут DEFAULT (например, для столбца ProductCount), значение NULL. При этом неуказанные столбцы (за исключением тех, которые имеют тип Serial) должны допускать значение NULL или иметь атрибут DEFAULT.
Если конкретные столбцы не указываются, как в первом примере, тогда мы должны передать значения для всех столбцов в таблице.
Также мы можем добавить сразу несколько строк:
INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price) VALUES ('iPhone 6', 'Apple', 3, 36000), ('Galaxy S8', 'Samsung', 2, 46000), ('Galaxy S8 Plus', 'Samsung', 1, 56000)
В данном случае в таблицу будут добавлены три строки.
Возвращение значений
Если мы добавляем значения только для части столбцов, то мы можем не знать, какие значения будут у других столбцов. Например, какое значени получит столбец Id у товара. С помощью оператора RETURNING мы можем получить это значение:
INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price) VALUES('Desire 12', 'HTC', 8, 21000) RETURNING id;