使用Npgsql在执行ExecuteScalar插入时检索串行ID

10

我试图向具有序列主键的PostgreSQL表中插入一行,并且需要在插入之后检索此列。我得到了类似这样的东西:

"pais"表有3列:id,pais,capital; id是一个序列列,也是其主键。

NpgsqlCommand query = new NpgsqlCommand("insert into pais(nombre, capital) values(@nombre, @capital)", conn);
query.Parameters.Add(new NpgsqlParameter("nombre", NpgsqlDbType.Varchar));
query.Parameters.Add(new NpgsqlParameter("capital", NpgsqlDbType.Varchar));
query.Prepare();
query.Parameters[0].Value = this.textBox1.Text;
query.Parameters[1].Value = this.textBox2.Text;
Object res = query.ExecuteScalar();
Console.WriteLine(res);

它在表中插入了一行,但“res”值为空。如果使用nexval('table_sequence')插入也会返回null。

有什么想法可以返回表的id吗?我有什么遗漏吗?

提前致谢


我不认为你的查询是要“选择”任何值作为标量返回的。 - Cos Callis
4个回答

27

这是线程安全的吗?
如果在您的插入和选择之间发生另一个插入,会发生什么? 为什么不使用:INSERT INTO table (fieldnames) VALUES (values) RETURNING idcolumn


2
如果选择语句在同一查询中,它是线程安全的,因为它在同一个“会话”中。来自http://www.postgresql.org/docs/8.4/interactive/functions-sequence.html:“因为这返回一个会话本地值,所以它可以给出可预测的答案,无论其他会话是否在当前会话执行nextval。” - markmnl
被接受的答案对我没用。这个可以,所以感谢你添加它。 - Leonard
1
为什么有时候它在数据库中创建了一条记录,但返回值却是-1? - Nick

21
insert into pais(nombre, capital) values(@nombre, @capital) RETURNING id

请将id替换为您的主键enter code here,然后使用

Object res = query.ExecuteScalar();

res 中,您将拥有 PK。


谢谢,那个可行。你需要将它转换为长整型,像这样: long lastID = (long) commandObj.ExecuteScalar(); - Najeeb

8
为了选择最后插入的身份标识,您需要使用:currval(sequencename) 因此,您的选择语句应如下所示:
NpgsqlCommand query = new NpgsqlCommand("insert into pais(nombre, capital) values(@nombre, @capital);select currval('table_sequence');", conn);

太棒了!我尝试了lastval(),它可以工作,但没有query.Prepare()这行代码,就像您链接的那篇文章所说。谢谢! - Cheluis
我认为 @mlapaglia 提供的 "INSERT INTO 表名 (字段名) VALUES (值) RETURNING id列名?" 是一个更好的解决方案。 - MBentley

3
插入操作本身不会返回值。当执行ExecuteScalar时,它会查找一个单一的“选定”值。
我认为您需要在插入操作之后跟上一个select语句来解决您的问题。如果您正在使用T-SQL,则可以按如下方式执行:
string sql = "INSERT INTO [Table] (FieldName) VALUES (@ParamName); " + "SELECT CAST(scope_identity() AS int)";
然后,ExecuteScalar将返回唯一的ID。
我不确定PostgreSQL的确切语法,但希望这能帮助您解决问题。

谢谢,我会查一下如何在PostgreSQL上实现。 - Cheluis
1
应该是字符串sql =“INSERT INTO [Table](FieldName)VALUES(@ParamName);”+“SELECT CAST(lastval()AS integer)”; - Cheluis
太好了。感谢您对确切语法的澄清。抱歉,我已经在 SQL Server 领域迷失多年了。 :) - Matt
别担心,这给了我灵感。 - Cheluis
可能在 SQL 翻译中迷失了方向? - default

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接