我在表格中插入了一些值。有一列其值是自动生成的。在我的代码的下一个语句中,我想要检索此值。
你能告诉我如何以正确的方式做到这一点吗?
答案 0 :(得分:56)
@@IDENTITY
不是范围安全的,如果原始表上有插入触发器,则会从另一个表中返回id,始终使用SCOPE_IDENTITY()
答案 1 :(得分:29)
这就是我使用自动生成的ID为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();
答案 2 :(得分:14)
如果你使用PHP和MySQL,你可以使用mysql_insert_id()函数,它会告诉你刚刚输入的项目的ID。
但是没有你的语言和DBMS,我只是在黑暗中拍摄。
答案 3 :(得分:14)
这在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语句插入多行,它的好处是返回所有ID。
答案 4 :(得分:11)
再次没有语言不可知的响应,但在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();
}
答案 5 :(得分:8)
如果您正在使用Oracle:
插入表格(字段....)值(值...)RETURNING(字段列表...)INTO(变量...)
示例:
插入人(姓名)值('杰克')将ID_PERSON归还给vIdPerson
或者如果您正在调用...带有CallableStatement的Java(sry,这是我的字段)
插入人(姓名)值('杰克')返回ID_PERSON INTO?
并声明语句的autput参数
答案 6 :(得分:6)
没有标准的方法(就像没有标准方法来创建自动递增ID一样)。以下是在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() 为您提供当前连接中使用的最后一个自动生成的序列值。
另一种方法是在 INSERT 语句中使用PostgreSQL的 RETURNING 子句:
INSERT INTO mytable (lastname) VALUES ('Cher') RETURNING id;
此表单返回一个结果集,就像 SELECT 语句一样,并且对于返回任何类型的计算默认值也很方便。
答案 7 :(得分:4)
从网站上我发现了以下内容:
SQL SERVER – @@IDENTITY vs SCOPE_IDENTITY() vs IDENT_CURRENT – Retrieve Last Inserted Identity of Record 2007年3月25日,由pinaldave
SELECT @@ IDENTITY 它返回在连接上生成的最后一个IDENTITY值,无论生成该值的表如何,也不管生成该值的语句的范围如何。 @@ IDENTITY将返回在当前会话中输入到表中的最后一个标识值。虽然@@ IDENTITY仅限于当前会话,但不限于当前范围。如果您在表上触发了导致在另一个表中创建标识的触发器,您将获得最后创建的标识,即使它是创建它的触发器。
SELECT SCOPE_IDENTITY() 它返回在连接上生成的最后一个IDENTITY值以及同一范围内的语句,而不管生成该值的表。 与@@ IDENTITY一样,SCOPE_IDENTITY()将返回在当前会话中创建的最后一个标识值,但它也会将其限制为当前范围。换句话说,它将返回您显式创建的最后一个标识值,而不是由触发器或用户定义函数创建的任何标识。
SELECT IDENT_CURRENT('tablename') 它返回表中生成的最后一个IDENTITY值,无论创建该值的连接如何,也不管生成该值的语句的范围如何。 IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表格。 IDENT_CURRENT返回在任何会话和任何范围内为特定表生成的标识值。
答案 8 :(得分:4)
一个重要的注意事项是,使用供应商SQL查询来检索最后插入的ID是安全的,而不必担心并发连接。
我一直认为您必须创建一个事务才能插入一行,然后选择最后插入的ID,以避免检索另一个客户端插入的ID。
但是这些特定于供应商的查询始终会检索当前与数据库的连接的最后插入ID 。这意味着最后插入的ID不会受到其他客户端插入的影响,只要它们使用自己的数据库连接即可。
答案 9 :(得分:3)
对于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列的值。
答案 10 :(得分:2)
请记住,@@ IDENTITY会返回当前连接最近创建的标识,而不一定是表中最近添加的行的标识。您应该始终使用SCOPE_IDENTITY()来返回最近添加的行的标识。
答案 11 :(得分:2)
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
答案 12 :(得分:2)
sql = "INSERT INTO MyTable (Name) VALUES (@Name);" +
"SELECT CAST(scope_identity() AS int)";
SqlCommand cmd = new SqlCommand(sql, conn);
int newId = (int)cmd.ExecuteScalar();
答案 13 :(得分:2)
这就是我使用参数化命令的方法。
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();
答案 14 :(得分:2)
您使用的数据库是什么?据我所知,没有数据库不可知的方法来做到这一点。
答案 15 :(得分:1)
Rob的答案将是与供应商无关的最多,但如果您使用 MySQL ,更安全和正确的选择将是内置的LAST_INSERT_ID()
函数。
答案 16 :(得分:0)
这适用于任何类型的数据库。
答案 17 :(得分:0)
基于环境的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
答案 18 :(得分:0)
SELECT @@Scope_Identity as Id
还有@@ identity,但是如果你有一个触发器,它将返回触发期间发生的事情的结果,其中scope_identity尊重你的范围。
答案 19 :(得分:0)
在TransactSQL中,您可以使用OUTPUT子句来实现它。
INSERT INTO my_table(col1,col2,col3) OUTPUT INSERTED.id VALUES('col1Value','col2Value','col3Value')
答案 20 :(得分:0)
最简单的答案:
command.ExecuteScalar()
默认返回第一列
返回值 键入:System.Object 结果集中第一行的第一列,如果结果集为空,则为空引用(在Visual Basic中为Nothing)。最多返回2033个字符。
从MSDN
复制