Tengo una tabla llamada Tabla1. Tiene muchas columnas, una de ellas es Column1. No conozco las otras columnas, incluso pueden cambiar algunas veces. Hay un tipo de cursor de refferencia fuertemente tipado que devuelve Table1% rowtype, llamado cur_Table1. Tengo un procedimiento almacenado llamado SP1 que tiene un parámetro out de tipo cur_Table1. Estoy llamando a este procedimiento almacenado SP1 desde otra base de datos que solo ve este procedimiento almacenado, pero no la tabla o el tipo en sí. ¿Cómo selecciono solo Column1 del cursor devuelto? Sé que puedo buscar en un registro o tantas variables como el cursor tiene columnas, pero solo sé de la existencia de una columna, por lo que no puedo declarar el registro completo o el número correcto de variables.Oracle: seleccione una columna específica de un cursor de referencia
Respuesta
Puede hacerlo con DBMS_SQL
, pero no es bonito.
de mesa y de la muestra de datos (COLUMN1 tiene los números 1 - 10):
create table table1(column1 number, column2 date, column3 varchar2(1000), column4 clob);
insert into table1
select level, sysdate, level, level from dual connect by level <= 10;
commit;
paquete con un procedimiento que se abre un cursor ref y selecciona todo:
create or replace package test_pkg is
type cur_Table1 is ref cursor return table1%rowtype;
procedure sp1(p_cursor in out cur_table1);
end;
/
create or replace package body test_pkg is
procedure sp1(p_cursor in out cur_table1) is
begin
open p_cursor for select column1, column2, column3, column4 from table1;
end;
end;
/
Bloque PL/SQL que lee datos COLUMN1 del cursor de ref .:
--Basic steps are: call procedure, convert cursor, describe and find columns,
--then fetch rows and retrieve column values.
--
--Each possible data type for COLUMN1 needs to be added here.
--Currently only NUMBER is supported.
declare
v_cursor sys_refcursor;
v_cursor_number number;
v_columns number;
v_desc_tab dbms_sql.desc_tab;
v_position number;
v_typecode number;
v_number_value number;
begin
--Call procedure to open cursor
test_pkg.sp1(v_cursor);
--Convert cursor to DBMS_SQL cursor
v_cursor_number := dbms_sql.to_cursor_number(rc => v_cursor);
--Get information on the columns
dbms_sql.describe_columns(v_cursor_number, v_columns, v_desc_tab);
--Loop through all the columns, find COLUMN1 position and type
for i in 1 .. v_desc_tab.count loop
if v_desc_tab(i).col_name = 'COLUMN1' then
v_position := i;
v_typecode := v_desc_tab(i).col_type;
--Pick COLUMN1 to be selected.
if v_typecode = dbms_types.typecode_number then
dbms_sql.define_column(v_cursor_number, i, v_number_value);
--...repeat for every possible type.
end if;
end if;
end loop;
--Fetch all the rows, then get the relevant column value and print it
while dbms_sql.fetch_rows(v_cursor_number) > 0 loop
if v_typecode = dbms_types.typecode_number then
dbms_sql.column_value(v_cursor_number, v_position, v_number_value);
dbms_output.put_line('Value: '||v_number_value);
--...repeat for every possible type
end if;
end loop;
end;
/
Guau ... y pensé que sería algo trivial como "seleccionar columna1 del cursor". – fejesjoco
No sé si es una opción o no, pero ¿no sería una mejor solución crear una función que devuelva el valor específico que está buscando? Eso evita la sobrecarga de enviar los datos adicionales. Alternativamente, podría definir un cursor con un conjunto de campos conocidos en el que las dos partes conocen.
No tengo control sobre la base de datos de SP, solo tengo que llamarlo desde otro lugar como cliente de un tercero. – fejesjoco
Dada la pregunta original, la respuesta de jonearles sigue siendo la correcta, así que lo dejo marcado como tal, pero terminé haciendo algo completamente diferente y mucho mejor.
El problema era/es que no tengo control sobre la base de datos del SP1, solo tengo que llamarlo desde otro lugar como un cliente externo. Ahora logré obtener permiso para ver no solo SP, sino también el tipo de cursor. Todavía no veo la mesa, pero ahora hay una solución mucho más limpio:
En la otra base de datos que se ha concedido acceso para ver este tipo ahora:
type cur_Table1 is ref cursor return Table1%rowtype;
Así que en mi base de datos que pueda hacer esto ahora:
mycursor OtherDB.cur_Table1;
myrecord mycursor%rowtype;
...
OtherDB.SP1(mycursor);
fetch mycursor into myrecord;
dbms_output.put_line(myrecord.Column1);
Ver, todavía no necesito ningún acceso a la tabla, solo veo el cursor. La clave es que el% de tipo de fila mágico también funciona para los cursores, no solo para las tablas. No funciona en sys_refcursor, pero lo hace en uno fuertemente tipado. Dado este código, no me tiene que importar si algo cambia en el otro lado, no tengo que definir todas las columnas o registros, solo especifico la columna que me interesa.
Me encanta esta actitud de OOP sobre Oracle.
- 1. ¿Cómo muevo el cursor a una fila y columna específica?
- 2. Django Seleccione la consulta con la columna específica
- 3. ¿Cómo obtiene resultados muy formateados de un procedimiento de Oracle que devuelve un cursor de referencia?
- 4. Columna de consulta padre de referencia en subconsulta (Oracle)
- 5. seleccione * vs seleccione la columna
- 6. Seleccione una columna SQL DISTINCT
- 7. ¿Cómo se detecta si hay un índice para una columna específica en una tabla en Oracle?
- 8. Una buena referencia para Oracle PL/SQL
- 9. Oracle: cómo colocar un subpartición de una partición específica
- 10. Oracle EJECUTAR INMEDIATO en un cursor
- 11. Oracle PLSQL: declare un cursor en una tabla no existente
- 12. Query MediaStore Cursor usando la carpeta específica
- 13. Seleccione una columna si la otra columna es nula
- 14. Seleccione una fila con valor distinto de una columna
- 15. Seleccione * y cree un alias sobre una columna
- 16. Seleccione una columna ficticia con un valor ficticio en SQL?
- 17. ¿Cuándo Oracle indexa valores nulos de columna?
- 18. Bucle a través de un cursor explícito en Oracle
- 19. ¿Cómo seleccionar una columna específica en LINQ?
- 20. SQL: Seleccione columna similar de dos tablas
- 21. aplicar strsplit a una columna específica en un data.frame
- 22. XSLT: Seleccione siguiente hermano hasta alcanzar una etiqueta específica
- 23. Cómo abrir un nuevo editor de eclipse con una posición de desplazamiento de cursor específica
- 24. Seleccione una sola columna del conjunto de datos con LINQ
- 25. Cómo consultar una columna CLOB en Oracle
- 26. ¿Cómo se prueba una serie de filas emparejadas igual X en una fila que hace referencia a una columna específica?
- 27. Oracle SQL Developer: ¿cómo ver los resultados de un cursor de ref?
- 28. R: agregado con función específica de columna
- 29. Columna específica de orientación en la tabla
- 30. Cambiar el tipo de datos de una columna en Oracle
Explique cómo propone llamar a un procedimiento en otra base de datos (o cualquier base de datos, para el caso) sin poder ver los tipos de los argumentos. –
Hice una "concesión de ejecución de SP a otro", pero no otorgué ninguna otra cosa, ni en la tabla ni en el paquete de tipos. Y funciona. – fejesjoco
Ah, y por el lado de las llamadas, pongo el parámetro out de SP en un sys_refcursor, por supuesto. – fejesjoco