Oracle中的参数化查询问题

18

我正在使用Oracle.DataAccess而不是过时的System.Data.OracleClient,但似乎在将多个参数传递到我的更新查询中遇到了问题。

这个可以工作。

OracleCommand.CommandText = "UPDATE db SET column1 = :param1 WHERE column2 = 'Y'"
OracleCommand.Parameters.Add(New OracleParameter("param1", "1234"))

但我希望能够传递多个参数。

这是我的完整代码。

    OracleConn.Open()
    OracleCommand = OracleConn.CreateCommand()
    OracleCommand.CommandText = "UPDATE db SET column1 = :param1 WHERE column2 = :param2"
    OracleCommand.CommandType = CommandType.Text
    OracleCommand.Parameters.Add(New OracleParameter("param1", "1234"))
    OracleCommand.Parameters.Add(New OracleParameter("param2", "Y"))
    OracleCommand.ExecuteNonQuery()

我的SELECT查询在传递多个参数时似乎可以工作,但更新参数时不能工作。


1
你使用了OracleCommand.ExecuteNonQuery()来执行SQL语句了吗? - Codo
1
你的 OracleCommand.CommandType 是什么? - Cos Callis
@Codo 我在那里使用了 OracleCommand.ExecuteNonQuery(),只是忘记将其放入我的示例中。 - Jamie Taylor
@Cos Callis 我已经设置成这样 OracleCommand.CommandType = CommandType.Text - Jamie Taylor
你使用的是哪个Oracle客户端? - Cos Callis
显示剩余7条评论
6个回答

36
虽然我看不出你的示例有什么问题,但我想知道你是否遇到了旧的“BindByName”问题。 默认情况下,ODP.NET将参数按照它们添加到集合中的顺序绑定到查询中,而不是按照它们的名称进行绑定。 尝试在OracleCommand对象上设置BindByNametrue,看看是否可以解决问题。
我已经遇到这个问题很多次了,所以我使用自己的工厂方法来创建命令,它会自动为我设置这个属性为true
经典无用的Oracle文档在这里

抢先一步了。当我看到选择器正常工作时,我正想着这个。 - Zach Green
太棒了!问题解决了 - 非常感谢,这个问题困扰我已经一个星期了! - Jamie Taylor
谢谢你的回答。如果使用通用的ADO.NET接口(DbCommand &c)而不是强类型的接口(OracleCommand &c),你有什么想法吗?也许可以在连接字符串中指定它吗? - Anton Shepelev
我的问题在这里得到了解答。 - Anton Shepelev

4

为了模拟System.Data.OracleClient的默认行为,您应该将OracleCommand设置为按名称绑定。

OracleCommand.BindByName = True

2

尝试使用指定类型的OracleParameter进行更新。在将其添加到参数列表之前,设置对象的值。

var param1 = new OracleParameter( "param1", OracleType.Int32 );
param1.Value = "1234";

OracleCommand.Parameters.Add( param1 );

2
在OracleParameter构造函数的第一个参数中不应使用冒号。应该是OracleParameter(“param1”,...)。 - Zach Green
1
好的,Zach说得对。我可能看的是旧文档。OracleParameter类文档 http://download.oracle.com/docs/html/B28089_01/OracleParameterClass.htm - Brian Dishaw
如果您更新您的答案,我相信我可以取消踩。 - Zach Green

1

试试这个,希望它能正常工作。它确实编译了。
不确定是否还需要发送提交...
我总是通过存储过程来完成这种操作,在更新语句之后有一个提交。

哈维·萨瑟

        OracleConnection ora_conn = new OracleConnection("connection string");

        OracleCommand ora_cmd = new OracleCommand("UPDATE db SET column1 = :param1 WHERE column2 = :param2", ora_conn);
        ora_cmd.CommandType = CommandType.Text;
        ora_cmd.BindByName = true;

        ora_cmd.Parameters.Add(":param1", OracleDbType.Varchar2, "1234", ParameterDirection.Input);
        ora_cmd.Parameters.Add(":param2", OracleDbType.Varchar2, "Y", ParameterDirection.Input);

        ora_cmd.ExecuteNonQuery();                

0
第一个代码块是正确的:在参数名称前使用冒号,但不要在OracleParameter的第一个参数中使用冒号。
如果没有抛出任何错误,则可能是UPDATE成功运行,只是根据WHERE子句及其替换参数值未更新任何记录。尝试在没有WHERE子句的测试表上执行,以确保它真正起作用。

我把WHERE子句删除了,但它仍然无法运行——如果我更改没有参数的查询,则可以正常工作。 - Jamie Taylor

0

这是我通常使用的结构类型(抱歉,这是从记忆中得出的):

int rows = 0;
using ( OracleConnection conn = new OracleConnection(connectionString) ) {
  using ( OracleCommand cmd = conn.CreateCommand() ) {
    cmd.CommandText = "UPDATE table SET column1 = ':p1 WHERE column2 = :p2";
    cmd.CommandType = CommandType.Text;
    cmd.Parameters.AddWithValue(":p1", p1Val);
    cmd.Parameters.AddWithValue(":p2", p2Val);
    rows = cmd.ExecuteNonQuery();
  }
}

关键区别在于使用AddWithValue - 我不记得为什么最终使用了它,但我记得使用其他方法时遇到了一些问题。

我认为我尝试使用AddWithValue,但它不在Oracle.DataAccess命名空间中 - 我认为它在System.OracleClient命名空间中,但那已经过时了。 - Jamie Taylor
这取决于您使用的框架版本。Microsoft将不再支持System.OracleClient,但这并不意味着您必须停止使用它。 - chris
我正在使用 .Net 4 框架 - 我希望找到一些能够未来证明的东西。 - Jamie Taylor

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