web-dev-qa-db-fra.com

ORA-01036: nom/numéro de variable illégal lors de l'exécution d'une requête via C #

J'essaie d'utiliser la requête ALTER USER pour la base de données Oracle en utilisant OracleCommand en C # dans le code suivant. Il crée la requête si les valeurs pour Nom d'utilisateur et mot de passe ne sont pas des chaînes vides. Mais je reçois une erreur "ORA-01036: illegal variable name/number" lorsque ExecuteNonQuery() est exécuté.

  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();                   


            }
        }

Pourriez-vous s'il vous plaît suggérer ce qui ne va pas avec ma mise en œuvre?.

7
jetty

La cause-racine

Dans Oracle, vous avez trois types d'instructions SQL (et en plus des blocs PL/SQL):

  • Instructions dans le langage de définition de données (DDL). Ces instructions modifient la structure de la base de données. Ils commencent généralement par les verbes "ALTER" ou "CREATE"
  • Instructions dans le langage de modification de données (DML). Là, les instructions modifient le contenu à l'intérieur des tables, laissant la structure de chaque table non modifiée. Ces instructions commencent généralement par "INSERT", "MERGE" ou "DELETE".
  • Des déclarations dans ce que j'appelle le "langage de requête" (il semble qu'il n'y ait pas de nom canonique pour celles-ci). Cette déclaration commence par le verbe "SELECT".

Les variables de liaison dans Oracle ne sont autorisées qu'à certains emplacements spéciaux dans DML et les instructions de requête. Vous essayez d'utiliser des variables de liaison dans des endroits où elles ne sont pas autorisées. D'où l'erreur.

Solution

Construisez votre déclaration sans variables de liaison. Construisez la chaîne de requête complète à la place en utilisant la concaténation de chaînes.

Si vous souhaitez nettoyer l'entrée avant de concaténer la chaîne, utilisez le package DBMS_ASSERT .

Contexte

Les variables de liaison ne peuvent être utilisées que si Oracle peut créer un plan de requête sans connaître la valeur de la variable. Pour les instructions DDL, il n'y a pas de plan de requête. Par conséquent, les variables de liaison ne sont pas autorisées.

Dans les instructions DML et de requête, les variables de liaison ne sont autorisées que lorsqu'elles sont utilisées dans un tuple (en ce qui concerne la théorie des ensembles sous-jacente), c'est-à-dire lorsque la valeur est comparée à la valeur d'une table ou insérée dans une table . Ils ne sont pas autorisés à modifier la structure du plan d'exécution (par exemple, modifier la table cible ou le nombre de comparaisons).

17
stefan.schwetschke

Je viens de passer plusieurs jours à vérifier les paramètres car je dois passer 60 à une procédure stockée. Il s'avère que l'un des noms de variables (que je charge dans une liste et passe à la méthode Oracle Write que j'ai créée) avait un espace dans le nom à la fin. Lors de la comparaison avec les variables de la procédure stockée, elles étaient identiques, mais dans l'éditeur que je comparais auparavant, je n'ai pas remarqué d'espace supplémentaire. Cela m'a rendu fou pendant les 4 derniers jours en essayant tout ce que je pouvais trouver et en changeant même le pilote .net Oracle. Je voulais juste jeter ça ici pour que ça puisse aider quelqu'un d'autre. Nous avons tendance à nous concentrer sur les personnages et à ignorer les espaces. . . 

7
SDanks

Vous avez défini un oracleCommand mais l'avez utilisé dans 'pour' . Cela signifie que vous ajoutez des paramètres de même nom à un seul OracleCommand . Vous devez utiliser cmd.Parameters.clear() pour actualiser vos paramètres.

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();                   


            }
        } 
4
Sargol

Oracle erro ORA-01036 signifie que la requête utilise une variable non définie quelque part. A partir d'une requête, nous pouvons déterminer quelles variables sont utilisées: toutes celles commençant par @. Toutefois, si vous entrez ceci dans une requête advacned, il est important de confirmer que toutes les variables ont un paramètre d'entrée correspondant, y compris la même casse dans le nom de la variable, si votre base de données Oracle est sensible à la casse.

2
Ravi Mavani
 cmd.Parameters.Add(new OracleParameter("GUSERID ", OracleType.VarChar)).Value = userId;

J'avais huit paramètres et l'un était avec un espace à la fin, comme indiqué dans le code ci-dessus pour "GUSERID". La suppression de l'espace et tout a commencé à fonctionner.

0
Sribin

Vous ne pouvez pas transmettre nom d'utilisateur/table à pl/sql avec paramètre. Vous pouvez créer une procédure et construire SQL et exécuter immédiatement pour y parvenir.

0
hkutluay

Pour les autres personnes qui obtiennent cette erreur et recherchent des informations à ce sujet, elle est également renvoyée si vous passez un paramètre de liaison et ne l'utilisez jamais. Je ne pouvais pas vraiment trouver cela énoncé clairement n'importe où, mais je devais le prouver par essais et erreurs. 

0
Beatscribe

Cette erreur se produit lorsque vous manquez également cmd.CommandType = System.Data.CommandType.StoredProcedure; 

0
mpora