使用 ADO.NET 的 PostgreSQL 参数化插入
Posted
技术标签:
【中文标题】使用 ADO.NET 的 PostgreSQL 参数化插入【英文标题】:PostgreSQL Parameterized Insert with ADO.NET 【发布时间】:2015-11-16 10:37:59 【问题描述】:我将 NpgSQL 与 PostgreSQL 和 ADO.NET 一起使用。请原谅我这周刚开始使用 PostgreSQL 和 NpgSQL 的问题的简单性。
这样的东西很好用:
[Test]
public void InsertNoParameters()
NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
conn.Open();
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (FirstName,LastName) VALUES ('Test','Tube')";
command.CommandText = sql;
command.ExecuteNonQuery();
conn.Close();
当我输入参数时,我收到错误消息: Npgsql.NpgsqlException:错误:42703:列“_firstname”不存在
[Test]
public void InsertWithParameters()
NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
conn.Open();
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (FirstName,LastName) VALUES (_FirstName,_LastName)";
command.CommandText = sql;
var parameter = command.CreateParameter();
parameter.ParameterName = "_FirstName";
parameter.Value = "Test";
command.Parameters.Add(parameter);
parameter = command.CreateParameter();
parameter.ParameterName = "_LastName";
parameter.Value = "Tube";
command.Parameters.Add(parameter);
command.ExecuteNonQuery();
conn.Close();
【问题讨论】:
大写 小写。仅使用小写字母或引用您的标识符(使用双引号)。 我只是尝试了所有小写的参数名称,我仍然得到同样的错误。 在 psql(或 pgadmin)中检查列的实际名称。 据我所知,包括 postgresql 驱动程序在内的大多数驱动程序都遵循 microsoft 的约定来识别带有@
前缀的参数,而不是下划线 (_
)
看起来它必须是一个@符号。这很奇怪,因为 @ 对函数参数无效。
【参考方案1】:
cmets 中的回答是正确的:
-
Npgsql 不支持 _ 作为参数占位符表示法。您应该使用 @ 或 :(所以是 @FirstName 或 :FirstName,而不是 _FirstName)。
PostgreSQL 会自动将您的表名和列名小写,除非它们被双引号引起来。对所有内容使用小写名称(更简单)或在 SQL 查询中引用标识符。
所以你的代码或多或少应该是这样的:
IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (first_name, last_name) VALUES (@FirstName,@LastName)";
command.CommandText = sql;
var parameter = command.CreateParameter();
parameter.ParameterName = "FirstName";
parameter.Value = "Test";
command.Parameters.Add(parameter);
【讨论】:
我不同意 #2 的建议。一般不应使用带引号的标识符。如果您使用引号定义字段,则每次引用该字段时也必须使用它们。所以最好是值得的(但它不会)。大小写与下划线是有争议的。在没有带引号的标识符的情况下,使用大小写名称确实可以正常工作,而且有时会更可取……取决于项目。 如果没有带引号的标识符,使用大小写名称将无法正常工作,因为 PostgreSQL 会将名称折叠为小写。这意味着Ident1
和ident1
将发生冲突。引用你的标识符并没有什么特别的错误——这是标准的 PostgreSQL 实践,并且在需要混合大小写的情况下是必需的。例如,将 C# 属性名称映射到数据库列(例如实体框架)的 O/RM 通常会引用所有标识符。
您可以使用大小写名称发出定义查询和数据查询,它会正常工作。 Postgres 将使用它的“不区分大小写”版本来处理它们,这意味着它们将小写。无法将小写名称映射到以大小写命名的对象属性的 ORM 可能也会对您使用下划线的其他建议有问题。使用带引号的标识符创建列的 ORM 正在创建用户将来必须支付的债务。
一切都会“正常”,直到您碰巧有两个相同的标识符(如果折叠成小写字母)。这就是为什么任何将标识符从区分大小写的语言(例如 C#)映射到 PostgreSQL 的 O/RM 都必须引用,否则迟早两个属性将折叠成相同的小写字母并繁荣。
如果您控制所有访问数据库的应用程序并且可以确保所有标识符都是不同的,那么不引用也没关系。如果您正在编写诸如 O/RM 之类的通用组件,那么您很有可能必须引用。这一切都取决于上下文。以上是关于使用 ADO.NET 的 PostgreSQL 参数化插入的主要内容,如果未能解决你的问题,请参考以下文章
生成 .ADO.net 实体数据模型时,postgresql 不会出现在数据源中