Я вставив деякі значення в таблицю. Є стовпець, значення якого генерується автоматично. У наступному викладі мого коду я хочу отримати це значення.
Чи можете ви сказати мені, як це зробити правильно?
Я вставив деякі значення в таблицю. Є стовпець, значення якого генерується автоматично. У наступному викладі мого коду я хочу отримати це значення.
Чи можете ви сказати мені, як це зробити правильно?
Відповіді:
@@IDENTITY
не є безпечним для області та поверне вам ідентифікатор з іншої таблиці, якщо у вас є тригер вставки в вихідній таблиці, завжди використовуйте SCOPE_IDENTITY()
Ось як я виконую свої процедури зберігання для MSSQL з автоматично згенерованим ідентифікатором.
CREATE PROCEDURE [dbo].[InsertProducts]
@id INT = NULL OUT,
@name VARCHAR(150) = NULL,
@desc VARCHAR(250) = NULL
AS
INSERT INTO dbo.Products
(Name,
Description)
VALUES
(@name,
@desc)
SET @id = SCOPE_IDENTITY();
Це дуже добре працює в SQL 2005:
DECLARE @inserted_ids TABLE ([id] INT);
INSERT INTO [dbo].[some_table] ([col1],[col2],[col3],[col4],[col5],[col6])
OUTPUT INSERTED.[id] INTO @inserted_ids
VALUES (@col1,@col2,@col3,@col4,@col5,@col6)
Це має перевагу повернення всіх ідентифікаторів, якщо ваш оператор INSERT вставляє кілька рядків.
Знову ж ніякої мовної агностичної відповіді, але в Java це виглядає так:
Connection conn = Database.getCurrent().getConnection();
PreparedStatement ps = conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
try {
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
rs.next();
long primaryKey = rs.getLong(1);
} finally {
ps.close();
}
Якщо ви працюєте з Oracle:
Вставка значень таблиці (поля ....) (значення ...) ПОВЕРНЕННЯ (список полів ...) В (змінні ...)
приклад:
ВСТАВИТИ В ЗНАЧЕННЯ ОСОБИ (ІМ'Я) ('JACK') ПОВЕРНЕННЯ ID_PERSON У VIdPerson
або якщо ви телефонуєте з ... Java із CallableStatement (о, це моє поле)
ВСТАВИТИ В ЗНАЧЕННЯ ОСОБИ (ІМ'Я) ('JACK') ПОВЕРНЕННЯ ІДЕНТИФІКАЦІЇ ОСОБИ?
і оголошення параметра введення для виписки
Немає стандартного способу зробити це (як не існує стандартного способу створення ідентифікаторів з автоматичним збільшенням). Ось два способи зробити це в PostgreSQL. Припустимо, це ваша таблиця:
CREATE TABLE mytable (
id SERIAL PRIMARY KEY,
lastname VARCHAR NOT NULL,
firstname VARCHAR
);
Ви можете зробити це у двох операторах, якщо вони є послідовними операторами в одному з'єднанні (це буде безпечно в PHP із об'єднанням пулів, оскільки PHP не передає з'єднання назад до пулу, доки ваш сценарій не буде зроблено):
INSERT INTO mytable (lastname, firstname) VALUES ('Washington', 'George');
SELECT lastval();
lastval () дає вам останнє автоматично згенероване значення послідовності, що використовується у поточному з'єднанні.
Інший спосіб полягає у використанні речення PostgreSQL RETURNING в інструкції INSERT :
INSERT INTO mytable (lastname) VALUES ('Cher') RETURNING id;
Ця форма повертає набір результатів так само, як оператор SELECT , а також зручна для повернення будь-якого обчисленого значення за замовчуванням.
Важливим зауваженням є те, що використання SQL-запитів постачальника для отримання останнього вставленого ідентифікатора безпечно використовувати, не побоюючись паралельних з'єднань.
Я завжди думав, що вам потрібно створити транзакцію, щоб ВСТАВИТИ рядок, а потім ВИБРАТИ останній вставлений ідентифікатор, щоб уникнути отримання ідентифікатора, вставленого іншим клієнтом.
Але ці запити конкретного постачальника завжди отримують останній вставлений ідентифікатор поточного підключення до бази даних . Це означає, що на останній вставлений ідентифікатор не можуть впливати інші вставки клієнта, якщо вони використовують своє власне підключення до бази даних.
Для SQL 2005:
Припускаючи наступне визначення таблиці:
CREATE TABLE [dbo].[Test](
[ID] [int] IDENTITY(1,1) NOT NULL,
[somevalue] [nchar](10) NULL,
)
Ви можете використовувати наступне:
INSERT INTO Test(somevalue)
OUTPUT INSERTED.ID
VALUES('asdfasdf')
Що поверне значення стовпця ID.
З сайту я дізнався такі речі:
SQL SERVER - @@ IDENTITY vs SCOPE_IDENTITY () vs IDENT_CURRENT - Отримати останню вставку ідентифікаційного запису 25 березня 2007 р. Від pinaldave
SELECT @@ IDENTITY Він повертає останнє значення IDENTITY, створене у з'єднанні, незалежно від таблиці, яка створила значення, і незалежно від обсягу оператора, що створив значення. @@ IDENTITY поверне останнє значення ідентичності, введене до таблиці у вашому поточному сеансі. Хоча @@ IDENTITY обмежується поточним сеансом, він не обмежується поточним обсягом. Якщо у вас є тригер в таблиці, який викликає створення ідентичності в іншій таблиці, ви отримаєте ідентичність, яка була створена останньою, навіть якщо це був тригер, який її створив.
SELECT SCOPE_IDENTITY () Він повертає останнє значення IDENTITY, створене для з'єднання та за допомогою оператора в одному і тому ж обсязі, незалежно від таблиці, яка створила значення. SCOPE_IDENTITY (), як @@ IDENTITY, поверне останнє значення ідентичності, створене в поточному сеансі, але також обмежить його вашим поточним обсягом. Іншими словами, він поверне останнє значення ідентичності, яке ви явно створили, а не будь-яке посвідчення, створене тригером або визначеною користувачем функцією.
SELECT IDENT_CURRENT ('ім'я таблиці') Він повертає останнє значення IDENTITY, створене в таблиці, незалежно від з'єднання, яке створило значення, і незалежно від обсягу оператора, що створив значення. IDENT_CURRENT не обмежується обсягом та сеансом; він обмежений вказаною таблицею. IDENT_CURRENT повертає значення ідентичності, створене для певної таблиці в будь-якому сеансі та будь-якій області.
Яку базу даних ви використовуєте? Наскільки мені відомо, для цього не існує методу агностики бази даних.
Ось як я це робив, використовуючи параметризовані команди.
MSSQL
INSERT INTO MyTable (Field1, Field2) VALUES (@Value1, @Value2);
SELECT SCOPE_IDENTITY();
MySQL
INSERT INTO MyTable (Field1, Field2) VALUES (?Value1, ?Value2);
SELECT LAST_INSERT_ID();
sql = "INSERT INTO MyTable (Name) VALUES (@Name);" +
"SELECT CAST(scope_identity() AS int)";
SqlCommand cmd = new SqlCommand(sql, conn);
int newId = (int)cmd.ExecuteScalar();
Пані SQL Server: це хороше рішення, навіть якщо ви вставляєте більше рядків:
Declare @tblInsertedId table (Id int not null)
INSERT INTO Test ([Title], [Text])
OUTPUT inserted.Id INTO @tblInsertedId (Id)
SELECT [Title], [Text] FROM AnotherTable
select Id from @tblInsertedId
Відповідь Роба була б найбільш агностичною для продавців, але якщо ви використовуєте MySQL, то вбудованою LAST_INSERT_ID()
функцією буде більш безпечний та правильний вибір .
SELECT @@Scope_Identity as Id
Існує також ідентичність @@, але якщо у вас є тригер, він поверне результати чогось, що сталося під час тригера, де scope_identity поважає вашу область.
Рішення Oracle на основі середовища:
CREATE OR REPLACE PACKAGE LAST
AS
ID NUMBER;
FUNCTION IDENT RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY LAST
AS
FUNCTION IDENT RETURN NUMBER IS
BEGIN
RETURN ID;
END;
END;
/
CREATE TABLE Test (
TestID INTEGER ,
Field1 int,
Field2 int
)
CREATE SEQUENCE Test_seq
/
CREATE OR REPLACE TRIGGER Test_itrig
BEFORE INSERT ON Test
FOR EACH ROW
DECLARE
seq_val number;
BEGIN
IF :new.TestID IS NULL THEN
SELECT Test_seq.nextval INTO seq_val FROM DUAL;
:new.TestID := seq_val;
Last.ID := seq_val;
END IF;
END;
/
To get next identity value:
SELECT LAST.IDENT FROM DUAL
У TransactSQL для досягнення цього можна використовувати речення OUTPUT.
INSERT INTO my_table(col1,col2,col3) OUTPUT INSERTED.id VALUES('col1Value','col2Value','col3Value')
Найпростіша відповідь:
command.ExecuteScalar()
за замовчуванням повертає перший стовпець
Тип значення, що повертається: System.Object Перший стовпець першого рядка в наборі результатів або нульове посилання (у Visual Basic немає нічого), якщо набір результатів порожній. Повертає максимум 2033 символи.
Скопійовано з MSDN