当对FETCH使用Npgsql库时,我找不到任何方法将游标ref作为参数传递给PostgreSQL命令。这个是可能的吗?
using (DbConnection connection = new NpgsqlConnection(connectionString))
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
var outCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
outCursor.Direction = ParameterDirection.Output;
// get a refcursor from somewhere
using (DbCommand commandGet = connection.CreateCommand())
{
commandGet.CommandText = "get_cursor";
commandGet.CommandType = CommandType.StoredProcedure;
commandGet.Parameters.Add(outCursor);
commandGet.Connection = connection;
commandGet.ExecuteNonQuery();
}
// try to use it
using (DbCommand commandFetch = connection.CreateCommand())
{
var inCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
inCursor.Direction = ParameterDirection.Input;
inCursor.Value = outCursor.Value;
// This commented out line using string interpolation works fine.
// Can it be done with a parameter, as I'm trying to do below?
//commandFetch.CommandText = $"FETCH 100 FROM \"{outCursor.Value}\"";
// The same inCursor pattern used here works fine when the cursor is being passed
// on to a function, but does not work for FETCH
commandFetch.CommandText = $"FETCH 100 FROM :cursor";
commandFetch.Parameters.Add(inCursor);
commandFetch.Connection = connection;
// This line fails for param-based version;
// works fine with string-interpolation version
using (var reader = commandFetch.ExecuteReader())
{
while (reader.Read())
{
int a = (int)reader[0];
}
}
}
// close it
using (DbCommand commandClose = connection.CreateCommand())
{
// I would like to be able to pass the cursor as a true parameter here, too
commandClose.CommandText = $"CLOSE \"{outCursor.Value}\"";
commandClose.Connection = connection;
var reader = commandClose.ExecuteNonQuery();
}
}
}注意注释的行:我可以让代码正常工作,我只想找到一种方法使其工作,将游标ref作为参数传递回。
我得到的例外是Npgsql.PostgresException : 42601: syntax error at or near "$1"。
传递一个普通字符串值参数(该参数看起来可能工作.)也会失败,但也有相同的例外。
如果要将输入游标传递给函数,则从输出游标创建输入游标的上述模式工作良好。
发布于 2019-05-13 17:42:15
This Stack Overflow answer加上它的后续注释基本上回答说,由于底层数据库中的一种轻量化,不可能完成我想要做的事情(至少在创建和执行动态SQL之前是不可能的)。
不能在FETCH语句中使用变量。使用动态SQL: EXECUTE格式(‘从%i取回所有“,foo);
因此,这不是Npgsql的限制,另一个答案中提出的解决方案也可以应用于Npgsql。或者,您只需将字符串插入到SQL中即可,这在某种程度上是“丑陋的”(至少对我来说是如此),实际上是非常安全的。
(在这种情况下--但直接将值插入SQL通常是个坏主意,至少无需三思为什么,甚至在任何给定的有限使用中-在所有可能的情况下,它都是安全的,不受注入攻击。)
https://stackoverflow.com/questions/56112658
复制相似问题