2010-03-22 2 views
0

Je dois générer des instructions de mise à jour basées sur une table dans notre base de données. J'ai créé le script suivant qui génère les instructions de mise à jour dont j'ai besoin. Mais quand j'essaye d'exécuter ces manuscrits j'obtiens des erreurs relatives aux guillemets simples non échappés dans le contenu et les caractères T qui ont une signification spéciale dans l'oracle. Je me suis occupé du problème & B et & T en réglant SET DEFINE OFF. Quel est le meilleur moyen d'échapper à des guillemets simples dans le contenu? Ici, si le prénom ou le nom de famille contient des guillemets simples, les instructions de mise à jour générées sont rompues. Quel est le meilleur moyen d'échapper ces guillemets simples dans le prénom et le nom de famille?Oracle 10g - Meilleure façon d'échapper des guillemets simples

Répondre

1

Vous pouvez utiliser REPLACE:

DECLARE 
    CURSOR C1 IS 
     SELECT * FROM EMPLOYEES; 

BEGIN 
    FOR I IN C1 
    LOOP 
     DBMS_OUTPUT.PUT_LINE('UPDATE EMPLOYEES SET 
      FIRST_NAME= ''' || REPLACE(I.FIRST_NAME,'''','''''') || ''', 
      LAST_NAME = ''' || REPLACE(I.LAST_NAME,'''','''''') || ''', 
      DOB = TO_DATE(''' || TO_CHAR(I.DOB,'DD/MM/YYYY') || '',''DD/MM/YYYY'')' 
      WHERE EMPLOYEE_ID = ' || I.EMPLOYEE_ID || ';'); 
    END LOOP; 
END; 

Notes:

  • Vous avez été absent un || après I.LAST_NAME.
  • Je suppose que I.EMPLOYEE_ID est un nombre - dans ce cas, je ne l'entourerais pas de guillemets.
  • Je suppose que I.DOB est une date - dans ce cas, je vous recommande de le convertir explicitement en une date.

ALTERNATIVE: Si vous êtes sur Oracle 10g ou plus tard, vous pouvez utiliser cette syntaxe alternative qui peut être plus facile à lire; et utiliser REPLACE pour le rendre un peu plus évident ce qui se passe - c'est ma préférence personnelle:

DECLARE 
    CURSOR C1 IS 
     SELECT * FROM EMPLOYEES; 

BEGIN 
    FOR I IN C1 
    LOOP 
     DBMS_OUTPUT.PUT_LINE(REPLACE(REPLACE(REPLACE(REPLACE(
     q'[UPDATE EMPLOYEES SET 
      FIRST_NAME= q'{#FIRST_NAME#}', 
      LAST_NAME = q'{#LAST_NAME#}', 
      DOB = DATE '#DOB#' 
      WHERE EMPLOYEE_ID = #EMPLOYEE_ID#; 
      ]' 
      ,'#FIRST_NAME#', I.FIRST_NAME) 
      ,'#LAST_NAME#', I.LAST_NAME) 
      ,'#DOB#', TO_CHAR(I.DOB,'YYYY-MM-DD')) 
      ,'#EMPLOYEE_ID#', I.EMPLOYEE_ID) 
      ); 
    END LOOP; 
END; 

ci-dessus a l'avantage qu'il est facile de repérer les erreurs possibles dans le SQL dynamique, qui n'est pas vérifiée à compiler le temps pour les erreurs de syntaxe.

+0

@Jeffrey: Merci pour vos commentaires. Le seul inconvénient avec cette approche, je vois est qu'avec les valeurs NULL, je veux dire si first_name est arrivé à être NULL dans la table, en utilisant REPLACE (I.FIRST_NAME, '' '', '' '' '' '), nous sommes insérer une chaîne vide dans la table qui, je pense, n'est pas la même chose que NULL. N'est-ce pas? Pour l'instant, même si c'est plus bavard, j'ai utilisé IF..ELSE pour vérifier NULL et si non, j'ai utilisé q '(I.first_name)' et ainsi de suite. Ça marche. Encore une fois merci pour les commentaires. – Dharam

+0

Non. Dans Oracle, la chaîne vide est la même que NULL. –

+0

L'alternative avec Q-quotes est incomplète. Les guillemets simples resteront non échappés dans les instructions de mise à jour générées. Vous aurez besoin d'utiliser des Q-quotes à l'intérieur pour envelopper les colonnes de texte ainsi que _and_ avec des délimiteurs différents. par exemple. '# # FIRST_NAME # '' devrait être 'q {' # FIRST_NAME # '}' –

Questions connexes