initcap - case en sql ejemplos
ACTUALIZACIÓN con CASE e IN-Oracle (5)
Escribí una consulta que funciona como un encanto en SQL Server. Desafortunadamente, debe ejecutarse en una base de datos Oracle. He estado buscando en la web una solución de cómo convertirla, sin éxito: /
La consulta se ve así en 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`
Mi problema también es que las columnas budgetpost_gr1
y budgetpost son alfanuméricas y Oracle parece querer ver la lista como números. La lista son variables / parámetros que están predefinidos como listas separadas por comas, que simplemente se vuelcan en la consulta.
"La lista son variables / parámetros que están predefinidos como listas separadas por comas". ¿Quieres decir que tu consulta es en realidad
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 es así, necesitas una función para tomar una cadena y analizarla en una lista de números.
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;
/
Entonces puedes usar la función así:
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''
Hay otra solución que puede utilizar para actualizar utilizando una unión. Este ejemplo a continuación asume que desea des-normalizar una tabla incluyendo un valor de búsqueda (en este caso, almacenar un nombre de usuario en la tabla). La actualización incluye una combinación para encontrar el nombre y la salida se evalúa en una declaración CASE que admite que el nombre se encuentre o no se encuentre. La clave para hacer que esto funcione es asegurar que todas las columnas que salen de la unión tengan nombres únicos. En el código de ejemplo, observe cómo b.user_name entra en conflicto con la columna a.user_name y debe tener un alias con el nombre único "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;
Tengo una solución que se ejecuta. Aunque no sé si es óptimo. Lo que hago es dividir la cadena de acuerdo con http://blogs.oracle.com/aramamoo/2010/05/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement.html
Utilizando:
select regexp_substr('' 1, 2 , 3 '',''[^,]+'', 1, level) from dual
connect by regexp_substr(''1 , 2 , 3 '', ''[^,]+'', 1, level) is not null;
Entonces mi código final se ve así: ( $bp_gr1''
son cadenas como 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;
¿Hay alguna manera de hacerlo correr más rápido?
Use to_number
para convertir budgpost
en un número:
when to_number(budgpost,99999) in (1001,1012,50055) THEN ''BP_GR_A''
EDITAR: asegúrese de que haya suficientes 9
en to_number
para coincidir con la publicación de presupuesto más grande.
Si hay publicaciones presupuestarias no numéricas, puede filtrarlas con una cláusula where
al final de la consulta:
where regexp_like(budgpost, ''^-?[[:digit:],.]+$'')
Usted dijo que budgetpost es alfanumérico. Eso significa que está buscando comparaciones con cadenas. Debería intentar encerrar sus parámetros en comillas simples (y le falta el THEN final en la expresión del Caso).
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