J'ai écrit une requête qui fonctionne comme un charme dans SQL Server. Malheureusement, il doit être exécuté sur une base de données Oracle. J'ai cherché sur le Web à l'envers pour trouver une solution sur la façon de le convertir, sans succès: /
La requête ressemble à ceci dans SQL:
UPDATE tab1 SET budgpost_gr1=
CASE WHEN (budgpost in (1001,1012,50055)) THEN 'BP_GR_A'
WHEN (budgpost in (5,10,98,0)) THEN 'BP_GR_B'
WHEN (budgpost in (11,876,7976,67465))
ELSE 'Missing' END`
Mon problème est également que les colonnes budgetpost_gr1
et budgetpost est alphanumérique et Oracle semble vouloir voir la liste sous forme de nombres. La liste est constituée de variables/paramètres prédéfinis en tant que listes séparées par des virgules, qui sont simplement transférées dans la requête.
Vous avez une solution qui fonctionne. Je ne sais pas si c'est optimal. Ce que je fais est de diviser la chaîne en fonction de http://blogs.Oracle.com/aramamoo/2010/05/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement.html
En utilisant:select regexp_substr(' 1, 2 , 3 ','[^,]+', 1, level) from dual
connect by regexp_substr('1 , 2 , 3 ', '[^,]+', 1, level) is not null;
Donc, mon code final ressemble à ceci ($bp_gr1'
sont des chaînes comme 1,2,3
):
UPDATE TAB1
SET BUDGPOST_GR1 =
CASE
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( '$BP_GR1',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR1',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR1'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( ' $BP_GR2',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR2',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR2'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( ' $BP_GR3',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR3',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR3'
WHEN ( BUDGPOST IN (SELECT REGEXP_SUBSTR ( '$BP_GR4',
'[^,]+',
1,
LEVEL )
FROM DUAL
CONNECT BY REGEXP_SUBSTR ( '$BP_GR4',
'[^,]+',
1,
LEVEL )
IS NOT NULL) )
THEN
'BP_GR4'
ELSE
'SAKNAR BUDGETGRUPP'
END;
Existe-t-il un moyen de le faire fonctionner plus rapidement?
Vous avez dit que budgetpost est alphanumérique. Cela signifie qu'il recherche des comparaisons avec des chaînes. Vous devriez essayer de placer vos paramètres entre guillemets simples (et il vous manque le THEN final dans l'expression Case).
UPDATE tab1
SET budgpost_gr1= CASE
WHEN (budgpost in ('1001','1012','50055')) THEN 'BP_GR_A'
WHEN (budgpost in ('5','10','98','0')) THEN 'BP_GR_B'
WHEN (budgpost in ('11','876','7976','67465')) THEN 'What?'
ELSE 'Missing'
END
Utilisation to_number
pour convertir budgpost
en un nombre:
when to_number(budgpost,99999) in (1001,1012,50055) THEN 'BP_GR_A'
EDIT: assurez-vous qu'il y a suffisamment de 9
'péché to_number
pour correspondre au poste budgétaire le plus important.
S'il existe des postes budgétaires non numériques, vous pouvez les filtrer avec une clause where
à la fin de la requête:
where regexp_like(budgpost, '^-?[[:digit:],.]+$')
Msgstr "La liste est des variables/paramètres prédéfinis comme des listes séparées par des virgules". Voulez-vous dire que votre requête est en fait
UPDATE tab1 SET budgpost_gr1=
CASE WHEN (budgpost in ('1001,1012,50055')) THEN 'BP_GR_A'
WHEN (budgpost in ('5,10,98,0')) THEN 'BP_GR_B'
WHEN (budgpost in ('11,876,7976,67465'))
ELSE 'Missing' END`
Si c'est le cas, vous avez besoin d'une fonction pour prendre une chaîne et l'analyser dans une liste de nombres.
create type tab_num is table of number;
create or replace function f_str_to_nums (i_str in varchar2) return tab_num is
v_tab_num tab_num := tab_num();
v_start number := 1;
v_end number;
v_delim VARCHAR2(1) := ',';
v_cnt number(1) := 1;
begin
v_end := instr(i_str||v_delim,v_delim,1, v_start);
WHILE v_end > 0 LOOP
v_cnt := v_cnt + 1;
v_tab_num.extend;
v_tab_num(v_tab_num.count) :=
substr(i_str,v_start,v_end-v_start);
v_start := v_end + 1;
v_end := instr(i_str||v_delim,v_delim,v_start);
END LOOP;
RETURN v_tab_num;
end;
/
Ensuite, vous pouvez utiliser la fonction comme suit:
select column_id,
case when column_id in
(select column_value from table(f_str_to_nums('1,2,3,4'))) then 'red'
else 'blue' end
from user_tab_columns
where table_name = 'EMP'
Il existe une autre solution de contournement que vous pouvez utiliser pour mettre à jour à l'aide d'une jointure. Cet exemple ci-dessous suppose que vous souhaitez dénormaliser une table en incluant une valeur de recherche (dans ce cas, stocker un nom d'utilisateur dans la table). La mise à jour inclut une jointure pour rechercher le nom et la sortie est évaluée dans une instruction CASE qui prend en charge le nom trouvé ou introuvable. La clé pour que cela fonctionne est de s'assurer que toutes les colonnes sortant de la jointure ont des noms uniques. Dans l'exemple de code, remarquez comment b.user_name entre en conflit avec la colonne a.user_name et doit être aliasé avec le nom unique "user_user_name".
UPDATE
(
SELECT a.user_id, a.user_name, b.user_name as user_user_name
FROM some_table a
LEFT OUTER JOIN user_table b ON a.user_id = b.user_id
WHERE a.user_id IS NOT NULL
)
SET user_name = CASE
WHEN user_user_name IS NOT NULL THEN user_user_name
ELSE 'UNKNOWN'
END;