2010-08-16 4 views
2

Nous construisons un programme client dans lequel les paramètres de stockage dans un serveur Web avec Oracle backend sont définis dans le programme client .Net et téléchargés sous forme de jeu de données via webservice.Instruction UPDATE dans Oracle

Dans le code de service Web, les données sont lues à partir de l'ensemble de données et ajoutées aux instructions UPDATE sur le serveur Web (Oracle backend). Comme le serveur s'exécutera sur le réseau local du client derrière un pare-feu et en raison de la nature dynamique des paramètres impliqués, aucun sproc n'est utilisé - les chaînes SQL sont intégrées dans la logique.

Voici un exemple de chaîne:

UPDATE WorkOrders 
    SET TravelTimeHours = :TravelTimeHours, 
     TravelTimeMinutes = :TravelTimeMinutes, 
     WorkTimeHours = :WorkTimeHours, 
     WorkTimeMinutes = :WorkTimeMinutes, 
     CompletedPersonID = :CompletedPersonID, 
     CompletedPersonName = :CompletedPersonName, 
     CompleteDate = :CompleteDate 
WHERE WorkOrderNumber = :WorkOrderNumber 

Lorsque le code de débogage dans VS 2010 et entrer dans le code du serveur, nous recevons l'erreur suivante:

ORA-01036: illegal variable name/number 

lors de l'exécution de la commande SQL de la destination machine oracle, nous avons été invités à entrer les variables de liaison pour l'instruction ci-dessus, et aussi longtemps que nous avons utilisé le format de date correct, l'instruction UPDATE a fonctionné correctement.

QUESTIONS:

1) est-il possible que l'oracle a jeté l'erreur ORA-01036 lorsque le format mois a eu tort? 2) pourquoi ne devons-nous pas convertir le format de date depuis le site ASP.net fonctionnant sur la machine Oracle? Oracle a-t-il une routine de conversion par défaut qui exclut l'écran d'entrée de la variable de rattachement?

3) si le format de date n'a pas été le problème, qu'est-ce que signifie précisément ORA-1036 et comment puis-je découvrir quelle variable a un nom illégal/numéro?


C'est un extrait d'une fonction qui prend le type de l'ensemble de données (WOName) et retourne la chaîne SQL appropriée. De nombreux cas existent mais ont été supprimés pour plus de lisibilité.

Private Function GetMainSQLString(ByVal WOName As String) As String 
    Dim Result As String = "" 
    Select Case WOName 
     Case "Monthly Site Inspection"    
      Dim sb As New StringBuilder 
      sb.Append("UPDATE WorkOrders SET ") 
      sb.Append("CompletedPersonID = :CompletedPersonID, CompletedPersonName = :CompletedPersonName, CompleteDate = :CompleteDate, ") 
      sb.Append("SupervisorID = :SupervisorID, SupervisorName = :SupervisorName ") 
      sb.Append("WHERE WorkOrderNumber = :WorkOrderNumber") 
      Result = sb.ToString 
    End Select 
    Return Result 
End Function 

C'est un extrait d'une fonction qui prend l'objet de commande Oracle BYREF et ajoute les paramètres nécessaires à elle, selon lequel des 15 possibles types de jeu de données (WOName) est reçu du programme client. De nombreux cas existent mais ont été supprimés pour plus de lisibilité.

L'objet Cmd mis à jour est ensuite renvoyé à la logique de programme principale, où ExecuteNonQuery() est appelée.

Les valeurs de test de params ci-dessous sont les suivantes:

dr.Item("CompletedPersonID") 21 
dr.Item("CompletedPersonName") Pers Name 
dr.Item("CompleteDate")  #8/16/2010# 
dr.Item("SupervisorID")  24 
dr.Item("SupervisorName") Sup Name 
dr.Item("WorkOrderNumber") 100816101830 


Private Function addMainCmdParams(ByVal WOName As String, ByRef cmd As OracleCommand, ByVal dr As DataRow) As OracleCommand 
    Select Case WOName 
     Case "Monthly Site Inspection"    
      cmd.Parameters.Add(":CompletedPersonID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("CompletedPersonID") 
      cmd.Parameters.Add(":CompletedPersonName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("CompletedPersonName") 
      cmd.Parameters.Add(":CompleteDate", Oracle.DataAccess.Client.OracleDbType.Date).Value = dr.Item("CompleteDate") 
      cmd.Parameters.Add(":SupervisorID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("SupervisorID") 
      cmd.Parameters.Add(":SupervisorName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("SupervisorName") 
      cmd.Parameters.Add(":WorkOrderNumber", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("WorkOrderNumber") 
    End Select 
    Return cmd 
End Function 

Pendant l'exécution aujourd'hui, ce code précis a été un succès; mais un autre cas similaire n'était pas. Je me méfie toujours de tout typecasting implicite effectué par Oracle (le cas échéant) - et je me méfie particulièrement de la façon dont Oracle gère l'un de ces paramètres qui sont passés avec un dbNull.value - et je sais que ça va arriver. Donc, si c'est le problème, je vais devoir le contourner.Il y a trop de paramètres optionnels et de colonnes qui n'obtiennent pas toujours les valeurs passées pour que ce système brise les valeurs nulles.

Répondre

1

L'erreur n'a rien à voir avec les formats de date, cela signifie qu'une variable de l'instruction n'a pas été liée.

Cela peut être aussi simple qu'une faute d'orthographe (ce serait bien si Oracle incluait le nom de la variable dans le message d'erreur).

Pouvez-vous mettre à jour votre question avec le code qui crée, lie et exécute l'instruction?

+0

Merci pour votre réponse Thilo, je vais mettre à jour au travail demain. SF –

-1

Ceci est un extrait d'une fonction qui prend le type de l'ensemble de données (WOName) et renvoie la chaîne SQL appropriée. De nombreux cas existent mais ont été supprimés pour plus de lisibilité.

Private Function GetMainSQLString(ByVal WOName As String) As String 
    Dim Result As String = "" 
    Select Case WOName 
     Case "Monthly Site Inspection"    
      Dim sb As New StringBuilder 
      sb.Append("UPDATE WorkOrders SET ") 
      sb.Append("CompletedPersonID = :CompletedPersonID, CompletedPersonName = :CompletedPersonName, CompleteDate = :CompleteDate, ") 
      sb.Append("SupervisorID = :SupervisorID, SupervisorName = :SupervisorName ") 
      sb.Append("WHERE WorkOrderNumber = :WorkOrderNumber") 
      Result = sb.ToString 
    End Select 
    Return Result 
End Function 

C'est un extrait d'une fonction qui prend l'objet de commande Oracle BYREF et ajoute les paramètres nécessaires à elle, selon lequel des 15 possibles types de jeu de données (WOName) est reçu du programme client. De nombreux cas existent mais ont été supprimés pour plus de lisibilité.

L'objet Cmd mis à jour est ensuite renvoyé à la logique de programme principale, où ExecuteNonQuery() est appelée.

Les valeurs de test de params ci-dessous sont les suivantes:

dr.Item("CompletedPersonID") 21 
dr.Item("CompletedPersonName") Pers Name 
dr.Item("CompleteDate")  #8/16/2010# 
dr.Item("SupervisorID")  24 
dr.Item("SupervisorName") Sup Name 
dr.Item("WorkOrderNumber") 100816101830 


Private Function addMainCmdParams(ByVal WOName As String, ByRef cmd As OracleCommand, ByVal dr As DataRow) As OracleCommand 
    Select Case WOName 
     Case "Monthly Site Inspection"    
      cmd.Parameters.Add(":CompletedPersonID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("CompletedPersonID") 
      cmd.Parameters.Add(":CompletedPersonName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("CompletedPersonName") 
      cmd.Parameters.Add(":CompleteDate", Oracle.DataAccess.Client.OracleDbType.Date).Value = dr.Item("CompleteDate") 
      cmd.Parameters.Add(":SupervisorID", Oracle.DataAccess.Client.OracleDbType.Int32).Value = dr.Item("SupervisorID") 
      cmd.Parameters.Add(":SupervisorName", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("SupervisorName") 
      cmd.Parameters.Add(":WorkOrderNumber", Oracle.DataAccess.Client.OracleDbType.Varchar2).Value = dr.Item("WorkOrderNumber") 
    End Select 
    Return cmd 
End Function 

Pendant l'exécution aujourd'hui, ce code précis a été un succès; mais un autre cas similaire n'était pas. Je me méfie toujours de tout typecasting implicite effectué par Oracle (le cas échéant) - et je me méfie particulièrement de la façon dont Oracle gère l'un de ces paramètres qui sont passés avec un dbNull.value - et je sais que ça va arriver. Donc, si c'est le problème, je vais devoir le contourner. Il y a trop de paramètres optionnels et de colonnes qui n'obtiennent pas toujours les valeurs passées pour que ce système brise les valeurs nulles.

+0

Vous auriez dû modifier votre question pour inclure cette information (ce que j'ai fait pour vous). Les réponses sont censées être, bien, * réponses *. – APC

3

Oracle "gotcha" qui peut provoquer cette erreur est le fait que, par défaut, Oracle mappe les paramètres aux symboles de paramètre dans la requête par séquence, pas par le nom. Si le nombre/type de paramètres ne correspond pas, vous obtenez une erreur comme celle-ci.

La solution est de dire Oracle de se lier par nom:

cmd.BindByName = true 

Sans plonger dans les détails de votre code, cela peut ou ne peut pas être la réponse à votre problème, mais ce paramètre doit être par défaut, et devrait faire partie de toute configuration de commande qui utilise des paramètres. C'est plutôt étonnant de voir cette déclaration résoudre certains problèmes obscurs.

EDIT: Cela suppose que vous utilisez le fournisseur d'accès aux données d'Oracle. Dans .NET, vous devriez utiliser ceci, pas le fournisseur Oracle de Microsoft.

Questions connexes