ORA-01036:通过C#运行查询时的非法变量名称/编号

jet*_*tty 9 c# oracle

我试图ALTER USER在C#中使用OracleCommand在以下代码中使用Oracle数据库查询.如果Username和password的值不是空字符串,它将创建查询.但是执行"ORA-01036: illegal variable name/number"时我收到错误ExecuteNonQuery().

  string updateQuery = "ALTER USER :user IDENTIFIED BY :password";
  connection = new OracleConnection(LoginPage.connectionString);
  connection.Open();                
  OracleCommand cmd = new OracleCommand(updateQuery, connection);
  cmd.Connection = connection;  
  for(int i=0;i<usersList.Count;i++)
        {
            if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
            {
                OracleParameter userName = new OracleParameter();
                userName.ParameterName = "user";
                userName.Value = selectedUsersArray[i];

                OracleParameter passwd = new OracleParameter();
                passwd.ParameterName = "password";
                passwd.Value = passwordArray[i];

                cmd.Parameters.Add(userName);
                cmd.Parameters.Add(passwd);

                cmd.Prepare();
                cmd.ExecuteNonQuery();                   


            }
        }
Run Code Online (Sandbox Code Playgroud)

你能否说一下我的实施有什么问题?

ste*_*hke 20

根本原因

在Oracle中,您有三种SQL语句(另外还有PL/SQL块):

  • 数据定义语言(DDL)中的语句.这些语句修改了数据库的结构.他们通常以动词"ALTER"或"CREATE"开头
  • 数据修改语言(DML)中的语句.有语句修改表内的内容,使每个表的结构保持不变.这些语句通常以"INSERT","MERGE"或"DELETE"开头.
  • 我称之为"查询语言"的陈述(似乎没有这些的规范名称).这些语句以动词"SELECT"开头.

Oracle中的绑定变量只允许在DML和查询语句中的某些特殊位置使用.您正尝试在不允许使用绑定变量的位置使用绑定变量.因此错误.

构建没有绑定变量的语句.使用字符串连接构建完整的查询字符串.

如果要在连接字符串之前清理输入,请使用DBMS_ASSERT包.

背景

绑定变量只能在Oracle可以在不知道变量值的情况下构建查询计划时使用.对于DDL语句,没有查询计划.因此不允许绑定变量.

在DML和查询语句中,只有在元组内部使用绑定变量时才会允许绑定变量(关于底层集合理论),即将值与表中的值进行比较或将值插入表中时.不允许他们更改执行计划的结构(例如,更改目标表或更改比较次数).


Bea*_*ibe 13

只是为了其他人收到此错误并查找有关它的信息,如果您碰巧传递了一个绑定参数然后从不使用它,它也会被抛出。我在任何地方都找不到明确说明的内容,但必须通过反复试验来证明这一点。

  • 为我修好了。花了 2 天时间试图解决这个问题。 (2认同)
  • 这也使用 Python + cx_Oracle 解决了我的问题,确实节省了时间,即将一步步执行我的查询。再次感谢 Oracle 提供的无用错误消息。 (2认同)

SDa*_*nks 8

我只花了几天检查参数,因为我必须将60传递给存储过程.事实证明,其中一个变量名称(我加载到列表中并传递给我创建的Oracle Write方法)最后在名称中有一个空格.当与存储过程中的变量进行比较时,它们是相同的,但在我用来比较它们的编辑器中,我没有注意到额外的空间.在过去的4天里,我开始疯狂地尝试我能找到的一切,甚至改变.net Oracle驱动程序.只是想把它扔出去,这样它可以帮助别人.我们倾向于专注于角色而忽略空间...


小智 7

您定义了一个 oracleCommand 但在“for”中使用了它。这意味着您正在向一个 OracleCommand 添加同名参数。您应该使用它cmd.Parameters.clear()来刷新您的参数。

for(int i=0;i<usersList.Count;i++)
        {
            if (!(selectedUsersArray[i].Equals("")) && !passwordArray[i].Equals(""))
            {
                cmd.Parameters.clear();//Add this line
                OracleParameter userName = new OracleParameter();
                userName.ParameterName = "user";
                userName.Value = selectedUsersArray[i];

                OracleParameter passwd = new OracleParameter();
                passwd.ParameterName = "password";
                passwd.Value = passwordArray[i];

                cmd.Parameters.Add(userName);
                cmd.Parameters.Add(passwd);

                cmd.Prepare();
                cmd.ExecuteNonQuery();                   


            }
        } 
Run Code Online (Sandbox Code Playgroud)


hku*_*uay 0

您不能使用参数将用户/表名传递给 pl/sql。您可以创建一个过程并构建 SQL,然后立即执行来实现这一目标。