Impossible to get back the Query result for PL/SQL scripts. It was working fine earlier in the afternoon but something might have gone wrong and now results have vanished from screen. What should I do?
Thank you!
The dummy query is just an example even if I should also get DUMMY as column header and X as a unique record in a "Query result" tab. In fact my script is such as below and works but gives no viewable data because the "Query Result" has gone. Before to reinstall Oracle SQL Dev I am wondering if on trick exists to fix this point for which I have found no valuable fix so far.
declare
v_tab varchar( 30 ):= 'MD_ALL_DETAIL_';
v_date1 varchar( 30 ):= '0827D';
v_date2 varchar( 30 ):= '0830';
v_tab1 varchar( 30 );
v_tab2 varchar( 30 );
v_sql varchar( 2000 );
begin
v_tab1 := v_tab || v_date1;
v_tab2 := v_tab || v_date2;
v_sql := '
with tab as(
select ' || v_date1 || ' flag, md1.*
from ' || v_tab1 || ' md1
union all
select ' || v_date2 || ' flag, md2.*
from ' || v_tab2 || ' md2
), tab2 as (
select *
from(
select tab.flag, tab.cat_mk_code, tab.cat_mk_iden, tab.b_entity_code, tab.b_entity_iden, tab.cat_be_code, tab.cat_be_iden, tab.bucket_code, tab.
bucket_iden, tab.m_entity_code, tab.application_code, tab.indicator_code, tab.indicator_iden, tab.measure_value, tab.user_code, tab.lock_flag,
tab.alter_date, tab.table_name
from tab
)pivot(
sum( measure_value )
for flag
in( ' || v_date1 || ' as MEASURE_0, ' || v_date2 || ' as MEASURE_1 )
) )
select * from tab2 where MEASURE_0<>MEASURE_1';
execute immediate v_sql;
end;'
This code (at the screenshot) doesn't do anything, so message you got ("PL/SQL procedure successfully completed") is all you can expect.
Run e.g.
select * from dual;
and SQL Developer will automatically open the missing "Query Result" tab.
If you want to "display" the result of a dynamic SQL, you'll have to select it into something. A simple example:
See? I'm selecting from DUAL (as your initial query does) INTO a local variable. The result is displayed within the Script output tab.
Your "new" code uses a more complex query, possibly returning more than a single column/row so you can't select into a scalar variable. I presume you'll have to create a TYPE, declare a local variable (a collection, probably) and then do something with the result.
https://docs.oracle.com/cd/E11882_01/appdev.112/e25519/executeimmediate_statement.htm#LNPLS01317
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then execute_immediate_statement never executes.
For example, this statement never increments the sequence:
EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL'
Related
i have a scenario where i need to create a dynamic query with some if/else statements, i have prepared the query but unable to use this inside loop below is the snippet of what i am trying to acheive.
Query :
select user_name into username from table1 where user ='user1';
for(query)
Loop
Dbms_output.put_line('user name ' || user_name);
END Loop;
is this possible to use the vaiable in the for loop ?
Not really. Notice in the 19c PL/SQL Reference it says:
cursor
Name of an explicit cursor (not a cursor variable) that is not open when the cursor FOR LOOP is entered.
You have to code this the long way, by explicitly fetching the cursor into a record until you hit cursorname%notfound, e.g.
create or replace procedure cheese_report
( cheese_cur in sys_refcursor )
as
type cheese_detail is record
( name varchar2(15)
, region varchar2(30) );
cheese cheese_detail;
begin
loop
fetch cheese_cur into cheese;
dbms_output.put_line(cheese.name || ', ' || cheese.region);
exit when cheese_cur%notfound;
end loop;
close cheese_cur;
end;
Test:
declare
cheese sys_refcursor;
begin
open cheese for
select 'Cheddar', 'UK' from dual union all
select 'Gruyere', 'France' from dual union all
select 'Ossau Iraty', 'Spain' from dual union all
select 'Yarg', 'UK' from dual;
cheese_report(cheese);
end;
/
Cheddar, UK
Gruyere, France
Ossau Iraty, Spain
Yarg, UK
In Oracle 21c you can simplify this somewhat, though you still have to know the structure of the result set:
create or replace procedure cheese_report
( cheese_cur in sys_refcursor )
as
type cheese_detail is record
( cheese varchar2(15)
, region varchar2(30) );
begin
for r cheese_detail in values of cheese_cur
loop
dbms_output.put_line(r.cheese || ', ' || r.region);
end loop;
end;
You could parse an unknown ref cursor using dbms_sql to find the column names and types, but it's not straightforward as you have to do every processing step yourself. For an example of something similar, see www.williamrobertson.net/documents/refcursor-to-csv.shtml.
For the below procedure I am getting the ora error as mentioned in the title while running in Oracle SQL developer
DECLARE
sqlstr VARCHAR2(1000);
CURSOR TabSubPartitions IS
SELECT TABLE_NAME, PARTITION_NAME
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'PART_TABLE'
ORDER BY PARTITION_NAME;
BEGIN
FOR aSubPart IN TabSubPartitions LOOP
IF TRUNC(LAST_DAY(SYSDATE)) = '31-07-2020' THEN
sqlstr := 'ALTER TABLE '||aSubPart.TABLE_NAME||' MODIFY PARTITION '||aSubPart.PARTITION_NAME|| ' ADD SUBPARTITION ' ||aSubPart.PARTITION_NAME||'_'||TO_CHAR(TRUNC(LAST_DAY(SYSDATE))+1, 'MON_YYYY')||' VALUES LESS THAN ( '||TO_DATE(TRUNC(LAST_DAY(SYSDATE))+2, 'SYYYY-MM-DD HH24:MI:SS' , 'NLS_CALENDER=GREGORIAN')||')' ;
EXECUTE IMMEDIATE sqlstr;
END IF;
END LOOP;
END;
Could anyone please help me. Many thanks in advance.
The main issue in the block itself is is here:
'NLS_CALENDER=GREGORIAN'
where it must be
'NLS_CALENDAR=GREGORIAN'
Moreover, you should not rely on implicite date conversions.
But there is also an issue with your resulting ALTER TABLE statement, which looks something like
ALTER TABLE MODIFY PARTITION ... VALUES LESS THAN ( 02.08.2020 00:00:00)
depending on session date settings (again because of implict date conversion). I doubt that Oracle accepts a timestamp like this. Make sure you produce a proper date literal (like DATE '2020-08-02') instead.
The whole corrected code:
DECLARE
sqlstr VARCHAR2(1000);
CURSOR TabSubPartitions IS
SELECT TABLE_NAME, PARTITION_NAME
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'PART_TABLE'
ORDER BY PARTITION_NAME;
BEGIN
FOR aSubPart IN TabSubPartitions LOOP
IF TRUNC(LAST_DAY(SYSDATE)) = DATE '2020-07-31' THEN
sqlstr :=
'ALTER TABLE ' || aSubPart.TABLE_NAME || ' MODIFY PARTITION ' || aSubPart.PARTITION_NAME ||
' ADD SUBPARTITION ' || aSubPart.PARTITION_NAME || '_' || TO_CHAR(TRUNC(LAST_DAY(SYSDATE))+1, 'MON_YYYY') ||
' VALUES LESS THAN (DATE ''' || TRIM(TO_CHAR(TRUNC(LAST_DAY(SYSDATE))+2, 'SYYYY-MM-DD', 'NLS_CALENDAR=GREGORIAN')) || ''')' ;
EXECUTE IMMEDIATE sqlstr;
END IF;
END LOOP;
END;
I have several pieces of advice.
First, modify your code to output the value of sqlstr, so you can see exactly what the SQL statement is that you are trying to execute. This should make it easier to understand where the syntax error is.
Second, change TRUNC(LAST_DAY(SYSDATE)) = '31-07-2020' to use an explicit date format when converting from date to string. Something like TO_CHAR(TRUNC(LAST_DAY(SYSDATE)), 'DD-MM-YYYY') .... I don't think this is related to your error, but it is better practice than relying on the implicit conversion format.
Third, look carefully at the TO_DATE call. As it is you appear to be calling TO_DATE with date parameter, then implicitly converting that back to a string. At best that's not necessary, and at worst it will cause unexpected behavior. I suspect you may simply mean to use TO_CHAR where you currently have TO_DATE.
I need to change the SRID (set it to NULL) in the geometry objects of all tables in a specific schema (for a specific user)
The command:
UPDATE my_table t SET t.geometrie.sdo_srid = null;
works fine for a single table.
When I try to do it in a loop for all tables of a specific owner:
BEGIN
FOR my_tables IN (
SELECT TABLE_NAME from all_tables where OWNER = 'LANDWERTZONEN' AND TABLE_NAME NOT LIKE 'GOOM%' AND TABLE_NAME NOT LIKE '%BKP'
)
LOOP
DBMS_OUTPUT.PUT_LINE('UPDATE ' || my_tables || ' t SET t.geometrie.sdo_srid = null');
END LOOP;
END;
I get the error:
pls-00306 wrong number or types of arguments in call to '||'
What could be the problem here?
Wrong concatenation? Wrong call?
Any suggestions are very welcome.
Besides the syntax error that Littlefoot pointed out, you may extend the logic to actually perform the update rather than printing out the UPDATE statement:
DECLARE
sql_stmt varchar2(256);
BEGIN
FOR st IN (
SELECT OWNER, TABLE_NAME, COLUMN_NAME
FROM all_tab_columns
WHERE OWNER = 'LANDWERTZONEN'
AND TABLE_NAME NOT LIKE 'GOOM%'
AND TABLE_NAME NOT LIKE '%BKP'
AND DATA_TYPE = 'SDO_GEOMETRY'
)
LOOP
sql_stmt := 'UPDATE ' || st.owner ||'.' || st.table_name || ' t SET t.'|| st.column_name ||'.sdo_srid = null';
DBMS_OUTPUT.PUT_LINE('Executing ' || sql_stmt);
execute immediate sql_stmt;
COMMIT;
END LOOP;
END;
/
This actually restricts the change to actual spatial tables / columns.
Note that you must make sure the spatial indexes are dropped before execution (and update metadata and recreate the spatial indexes after execution).
BUT I would question the reason for setting the SRIDs to NULL. This will seriously remove functionality: you will no longer be able to perform any measurements (area, length, distances). Also you will no longer be able to relate the data with data that has explicit SRIDs (like a GPS point). And if the data is actually geodetic (long/lat) then operations like within_distance, buffer generation ... are essentially no longer possible.
Our advice is to always explicitly use the correct SRIDs.
How about this:
DBMS_OUTPUT.PUT_LINE('UPDATE ' || my_tables.table_name || ' t SET t.geometrie.sdo_srid = null');
-----------
You forgot to add table name from a cursor.
I'm struggling since 1 hour to find out why this won't work and I finally said 'to hell with it, i'm heading to stackoverflow' :)
BEGIN
FOR c IN ( SELECT ID FROM projects where id <4 )
LOOP
EXECUTE IMMEDIATE 'insert into project_tools(pj_id,tool_id) values(' || c || ',81)' ;
END LOOP;
END;
I tried many variants of this but no luck!
Can you tell me what's wrong with the above block?
Thanks!
I see, then you should not use loop, you can solve it in one statement -->
insert /*+ append */ into project_tools(pj_id,tool_id)
select /*+ parallel(8) */ ID, 81 from projects where id < 4;
(parallel works only in EE, and the degree can be any high, oracle will handle it)
You can imporve it with to "make the session parallel" before execute the insert:
alter session enable parallel dml parallel 10;
Maybe something like;
declare sql_text varchar(2000);
BEGIN
FOR c IN ( SELECT ID FROM projects where id <4 )
LOOP
sql_text := 'insert into project_tools(pj_id,tool_id) values(' || c || ',81)' ;
EXECUTE IMMEDIATE sql_text;
END LOOP;
END;
I have cursor which is selecting data and it is running quite fine
CURSOR Crs_c1 IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
ltrim(rtrim(a.GLOBAL_ACCOUNT_CODE))||ltrim(rtrim(a.LOCAL_ACCOUNT_CODE)) GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a,V_GLOBAL_ACCOUNTS#GDW_LIVE c --V_LOCAL_ACCOUNTS#GDWPP_ANY a,V_GLOBAL_ACCOUNTS#GDWPP_ANY c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE=c.GLOBAL_ACCOUNT_CODE
AND not exists (SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE=b.C_CONTO_GLOBAL_GDW);
But at the time of insertion the code fails....
INSERT INTO conto_gdw
(C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
nvl(Rec_Crs_c1.LOCAL_ACCOUNT_NAME,'.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
May be this problem is occuring because of a single tuple (dataset). How can I find that culprit data?
I have checked all the data from cursor selection by taking it in a excel sheet, I could not find anything manually. Is there any way ORACLE would return me the failed data?
You need to have a proper exception handling while inserting data .Provide the output of the pl sql block .After than we can help you.
DECLARE
CURSOR Crs_c1
IS
SELECT a.GLOBAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_CODE,
a.LOCAL_ACCOUNT_NAME,
c.GLOBAL_ACCOUNT_TYPE t_conto,
LTRIM (RTRIM (a.GLOBAL_ACCOUNT_CODE))
|| LTRIM (RTRIM (a.LOCAL_ACCOUNT_CODE))
GLOBAL_LOCAL
FROM V_LOCAL_ACCOUNTS#GDW_LIVE a, V_GLOBAL_ACCOUNTS#GDW_LIVE c
WHERE a.enabled_flag = 'Y'
AND a.GLOBAL_ACCOUNT_CODE = c.GLOBAL_ACCOUNT_CODE
AND NOT EXISTS
(SELECT 1
FROM conto_gdw b -- considero solo i conti nuovi
WHERE a.LOCAL_ACCOUNT_CODE = b.c_conto_local_gdw
AND a.GLOBAL_ACCOUNT_CODE =
b.C_CONTO_GLOBAL_GDW);
Rec_Crs_c1 Crs_c1%ROWTYPE;
BEGIN
OPEN Crs_c1;
LOOP
FETCH Crs_c1 INTO Rec_Crs_c1;
EXIT WHEN Crs_c1%NOTFOUND;
INSERT INTO conto_gdw (C_CONTO_LOCAL_GDW,
S_CONTO_LOCAL_GDW,
C_CONTO_GLOBAL_GDW,
T_CONTO,
D_INIZIO,
GLOBAL_LOCAL)
VALUES (Rec_Crs_c1.LOCAL_ACCOUNT_CODE,
NVL (Rec_Crs_c1.LOCAL_ACCOUNT_NAME, '.'),
Rec_Crs_c1.GLOBAL_ACCOUNT_CODE,
Rec_Crs_c1.t_conto,
(v_anno_in * 100) + v_mese_in,
Rec_Crs_c1.GLOBAL_LOCAL);
END LOOP;
CLOSE Crs_c1;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error Message' || SQLERRM);
DBMS_OUTPUT.put_line( 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.LOCAL_ACCOUNT_CODE
|| 'LOCAL_ACCOUNT_CODE '
|| Rec_Crs_c1.LOCAL_ACCOUNT_NAME
|| 'GLOBAL_ACCOUNT_CODE :'
|| Rec_Crs_c1.GLOBAL_ACCOUNT_CODE
|| 'GLOBAL_ACCOUNT_TYPE '
|| Rec_Crs_c1.t_conto
|| 'GLOBAL_LOCAL'
|| Rec_Crs_c1.GLOBAL_LOCAL);
END;