Я вставил некоторые значения в таблицу. Существует столбец, значение которого автогенерируется. В следующем выражении моего кода я хочу получить это значение.
Можете ли вы рассказать мне, как это сделать правильно?
Я вставил некоторые значения в таблицу. Существует столбец, значение которого автогенерируется. В следующем выражении моего кода я хочу получить это значение.
Можете ли вы рассказать мне, как это сделать правильно?
@@IDENTITY
не является безопасным для области и вернет вам идентификатор из другой таблицы, если у вас есть триггер insert в исходной таблице, всегда используйте 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();
Если вы используете PHP и MySQL, вы можете использовать функцию mysql_insert_id(), которая сообщит вам идентификатор элемента, который вы только что внесли.
Но без вашего языка и СУБД я просто снимаю в темноте.
Это очень хорошо работает в 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:
Вставка в таблицу (поля...) значения (значения...) ВОЗВРАЩЕНИЕ (список полей...) INTO (переменные...)
Пример:
ВСТАВЬТЕ ЧЕЛОВЕК (НАЗВАНИЕ) ЗНАЧЕНИЯ ( "ДЖЕК" ) ВОЗВРАЩЕНИЕ ID_PERSON INTO vIdPerson
или если вы звоните с... Java с помощью CallableStatement (sry, it my field)
ВСТАВИТЬ В ЧЕЛОВЕК (НАЗВАНИЕ) ЗНАЧЕНИЯ ( "ДЖЕК" ) ВОЗВРАЩЕНИЕ ID_PERSON INTO?
и объявление параметра autput для оператора
Нет стандартного способа сделать это (так же, как нет стандартного способа создания автоинкрементных идентификаторов). Вот два способа сделать это в PostgreSQL. Предположим, что это ваша таблица:
CREATE TABLE mytable (
id SERIAL PRIMARY KEY,
lastname VARCHAR NOT NULL,
firstname VARCHAR
);
Вы можете сделать это в двух операциях, если они являются последовательными операторами в одном соединении (это будет безопасно в PHP с пулом соединений, поскольку PHP не возвращает соединение в пул до тех пор, пока ваш script не будет сделано):
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 SERVER - @@IDENTITY vs SCOPE_IDENTITY() против IDENT_CURRENT - Получить последнюю вставленную идентификационную запись 25 марта 2007 г. pinaldave
SELECT @@IDENTITY Он возвращает последнее значение IDENTITY, созданное в соединении, независимо от таблицы, которая произвела значение, и независимо от области действия оператора, который произвел значение. @@IDENTITY вернет последнее значение идентификатора, введенное в таблицу текущего сеанса. Хотя @@IDENTITY ограничен текущим сеансом, он не ограничивается текущей областью. Если у вас есть триггер в таблице, который заставляет создать личность в другой таблице, вы получите идентификатор, который был создан последним, даже если это был триггер, который его создал.
SELECT SCOPE_IDENTITY() Он возвращает последнее значение IDENTITY, созданное в соединении, и оператором в той же области действия, независимо от таблицы, которая произвела значение. SCOPE_IDENTITY(), например @@IDENTITY, вернет последнее значение идентификации, созданное в текущем сеансе, но оно также ограничит его и вашей текущей областью. Другими словами, он вернет последнее значение идентификатора, которое вы явно создали, а не любое удостоверение, созданное триггером или пользовательской функцией.
SELECT IDENT_CURRENT ('tablename) Он возвращает последнее значение IDENTITY, созданное в таблице, независимо от соединения, которое создало значение, и независимо от области действия оператора, который произвел значение. IDENT_CURRENT не ограничивается областью и сеансом; он ограничен указанной таблицей. IDENT_CURRENT возвращает значение идентификатора, сгенерированное для конкретной таблицы, в любом сеансе и в любой области.
Для 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.
Помните, что @@IDENTITY возвращает недавно созданный идентификатор для вашего текущего соединения, а не обязательно идентификатор недавно добавленной строки в таблице. Вы всегда должны использовать SCOPE_IDENTITY(), чтобы вернуть личность недавно добавленной строки.
Какую базу данных вы используете? Насколько мне известно, для этого не существует агностического метода базы данных.
Вот как я это сделал, используя параметризованные команды.
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();
Ms 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
Ответ Rob будет самым агронизирующим агентом, но если вы используете 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 Первый столбец первой строки в результирующем наборе или нулевая ссылка (Nothing в Visual Basic), если набор результатов пуст. Возвращает максимум 2033 символа.
Скопировано из MSDN