I get the following error message in a stored procedure that I created:
ORA-00933: SQL command not properly ended
ORA-06512: at line 11
I have tried Googling it, but could not find anything applicable as it tells my to try to eliminate any 'ORDER BY'.
declare
cursor a_tab is
select table_name
from all_tables
where owner = 'OFFERINGWORKSPACE'
and (TABLE_NAME like 'EBA_%' or TABLE_NAME = 'SURVEY_2.0');
v_tab_name varchar2(500);
begin
open a_tab;
loop
fetch a_tab into v_tab_name;
exit when a_tab%notfound;
EXECUTE IMMEDIATE 'delete ' || v_tab_name;
end Loop;
close a_tab;
open a_tab;
Loop
fetch a_tab into v_tab_name;
Exit when a_tab%notfound;
EXECUTE IMMEDIATE 'insert into ' || v_tab_name || '(select * from OFFERINGWORKSPACE.'||v_tab_name ||')';
End Loop;
Close a_tab;
End;
There is a clue in your cursor query:
... TABLE_NAME = 'SURVEY_2.0');
The period in that breaks the database object naming rules:
Nonquoted identifiers can only contain alphanumeric characters from your database character set and the underscore (_). Database links can contain periods (.) and "at" signs (#).
so that table name must be a quoted identifier. You therefore need to quote it in your statements:
EXECUTE IMMEDIATE 'delete "' || v_tab_name || '"';
and
EXECUTE IMMEDIATE 'insert into "' || v_tab_name
|| '"(select * from OFFERINGWORKSPACE."'||v_tab_name ||"')';
db<>fiddle showing the errors from those commands (simplified to one schema, and static SQL), and how adding the double quotes fixes them.
Related
I'm creating a function that accepts two parameters. And one of my parameter will serve as the database link for my statement. I've tried concatenating it. How will I be able to achieve this?
It shows this error
ORA-00923: FROM keyword not found where expected ORA-06512 at
"NOINK.CHECK_SECOND_REF_DIE", line 13.
Below is the code.
drop function check_second_ref_die;
create or replace function check_second_ref_die(lotNumber in VARCHAR2, db_link in VARCHAR2)
return varchar2
is
row_count NUMBER;
sql_statement VARCHAR2(300);
BEGIN
sql_statement := 'SELECT COUNT(*) FROM wcrepo.WCR_WAFER_REFERENCE#lepftds.itg.ti.com
WHERE waferconfigfile = (SELECT waferconfigfile FROM program_setup_rev#' || db_link ||
'WHERE device = (SELECT device FROM noink.lot WHERE lot_num = ' ||lotNumber || ')
AND setup_cnt=0) AND status =' || 'Approved' || 'AND ref_die_type =' || 'Secondary';
execute immediate sql_statement into row_count;
IF (row_count != 0) THEN
RETURN 'TRUE';
ELSE
RETURN'FALSE';
END IF;
END;
This is the code when I try to call the function
SELECT CASE
WHEN check_second_ref_die ('8019572', 'rfabtwdb.dal.make.ti.com') = 'TRUE'
THEN 'EXISTS' ELSE 'NOT EXISTS'
END
AS RESULT
FROM DUAL
AND status =' || 'Approved' || 'AND
This is wrong. Remove the concatenation operators and we have ...
AND status =ApprovedAND
... which is not valid SQL. To reference string literals you need to escape single quotes. The simplest way is to use two of them:
AND status =''Approved'' AND
You'll need to fix all the string literals in your code.
Dynamic SQL is hard because it turns compilation errors into runtime errors. You can make it easier to debug your code by including some simple instrumentation. If your code had this line before the EXECUTE IMMEDIATE you could have seen the executed statement and probably spotted the bloomer for yourself.
dbms_output.put_line(v_sql);
I have to write a function which edits predefined characteristics of a task. I'm using execute immediate but I'm getting this error:
> Error report -
ORA-00933: SQL command not properly ended
ORA-06512: at "C##U1519.BEARBEITE", line 7
ORA-06512: at line 2
00933. 00000 - "SQL command not properly ended"
This is my code
create or replace procedure bearbeite(Aufg_ID Aufgabe.Aufgaben_ID%TYPE, Eigenschaft VARCHAR2, Wert VARCHAR2)
as
sql_query_string2 VARCHAR2(4000);
begin
--überprüfen
sql_query_string2 := 'UPDATE Aufgabe SET ' || Eigenschaft || ' = ' || Wert || ' where Aufgabe.Aufgaben_ID = ' || Aufg_ID;
EXECUTE IMMEDIATE sql_query_string2;
exception
when no_data_found then
dbms_output.put_line('Kein Wert');
end;
-- test
set serveroutput on
begin
bearbeite(1,'Ort','TH WILDAU');
end;
What should I do in order to make it work? Thanks in advance
Dumping values into query strings is dangerous. The most advertised danger is SQL injection, but that doesn't apply in many cases (where user input might have controls already in place). A bigger issue is unexpected syntax errors. More than one person -- I'm sure -- has encountered a name like O'Neil to their detriment when generating a query string.
I strongly recommend the use of parameters. And this is easy in Oracle:
sql_query_string2 := 'UPDATE Aufgabe SET ' || Eigenschaft || ' = :1 where Aufgabe.Aufgaben_ID = :2';
EXECUTE IMMEDIATE sql_query_string2 USING Wert, Aufg_ID;
This also means that you don't have to worry about whether or not to use single quotes.
The parameters can be named rather than numbered.
Sadly, you cannot use parameters for SQL identifiers -- table names, schema names, column names, functions, key words. So, the column name does have to be incorporated into the string.
You should surround varchar2 argument with single quotes ... which in pl/sql should be escaped and becomes ''
sql_query_string2 := 'UPDATE Aufgabe SET ' || Eigenschaft || ' = ''' || Wert || ''' where Aufgabe.Aufgaben_ID = ' || Aufg_ID;
I am getting the following error:
00000 - "missing right parenthesis"
when I execute my procedure:
CREATE OR REPLACE PROCEDURE ALTER_TABLE_COLUMN_NOT_NULL(
var_tabname IN VARCHAR2,
var_clname IN VARCHAR2,
var_defvalue IN VARCHAR2 )
IS
l_isnull VARCHAR2(1);
BEGIN
SELECT isnull INTO l_isnull FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = var_tabname AND COLUMN_NAME = var_clname;
IF l_isnull = 'Y' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ' || var_tabname ||
' MODIFY COLUMN (' || var_clname ||
' DEFAULT ' || var_defvalue || ' NOT NULL)';
END IF;
END;
I know that according to the error, the right parenthesis is missing. I tried many ways of rewriting it, but I can't manage to fix it.
I am executing my procedure the following way:
BEGIN
ALTER_TABLE_COLUMN_NOT_NULL('FIRSTNAME', 'PRICE', '-');
END;
Writing dynamic SQL is hard, because compilation errors become runtime errors.
In this case I think the problem is that MODIFY COLUMN is wrong syntax. It's just MODIFY.
You may also run into some problems with your default of '-'. If price is a number that will fail because - is an invalid number. If price is a string you'll need to escape the passed value with additional quotes.
But probably you want to make this generic, so you need to write some more sophisticated handling which tests for datatype of the target column and formats default value appropriately.
"Can u give me a hint or any link how one can determine the datatype of a passed value in plsql?"
It's not the passed value which matters, it's the datatype of the modified column. You can get that from the USER_TAB_COLUMNS view which you're already querying.
Print your query to make sure it written correctly
DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || var_tabname || ' MODIFY COLUMN (' || var_clname || ' DEFAULT ' || var_defvalue || ' NOT NULL)');
This has been asked several times on the web, but none of the answers I found on Google could solve my problem.
I'd like to create a stored procedure that kills Oracle sessions. The only parameter the procedure accepts is the user name of the owner of the sessions to kill.
This is my attempt:
CREATE OR REPLACE PROCEDURE kill_user_session (
username IN NVARCHAR2
)
AS
stmt varchar(5000);
CURSOR get_sessions
IS
SELECT s.sid sid, s.serial# ser
FROM v$session s, v$process p
WHERE s.username = username
AND p.addr(+) = s.paddr;
session_rec get_sessions%ROWTYPE;
BEGIN
FOR session_rec in get_sessions LOOP
BEGIN
stmt := 'ALTER SYSTEM KILL SESSION ''' || session_rec.sid || ',' || session_rec.ser || '''';
EXECUTE IMMEDIATE stmt;
--EXCEPTION WHEN others THEN
-- dbms_output.put_line('Error killing session: ' || stmt);
-- dbms_output.put_line(SQLERRM);
END;
END LOOP;
END;
/
If I execute it like this
exec kill_user_session('myuser');
I get an error:
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at "SYSTEM.KILL_USER_SESSION", line 17
ORA-06512: at line 1
If I change line 17 to
stmt := 'ALTER SYSTEM KILL SESSION "' || session_rec.sid || ',' || session_rec.ser || '"';
then I get
ERROR at line 1:
ORA-00026: missing or invalid session ID
ORA-06512: at "SYSTEM.KILL_USER_SESSION", line 17
ORA-06512: at line 1
I have granted the following rights to SYSTEM:
GRANT SELECT ON v$session TO SYSTEM;
GRANT ALTER SYSTEM TO SYSTEM;
But that didn't help.
EDIT: I added a dbms_output.putline to print out the stmt variable before executing it. Here's an example:
ALTER SYSTEM KILL SESSION "34,91"
If I execute this statement outside of the stored procedure, it runs fine and the session is killed. But not from inside.
First off, you shouldn't have a semicolon in the SQL statement you pass to EXECUTE IMMEDIATE. That would cause the ORA-00911 error.
Second, it is always helpful to print out the dynamic SQL statement that you've built before you execute it. The extra semicolon may be the only error. Or there may be other errors. Those errors will inevitably be easier to debug if you can see the SQL statement that you've built (and execute it separately) rather than just looking at the code that builds the statement.
You can use this procedure:
{
CREATE PROCEDURE kill_user_session (users IN VARCHAR2)
AS
stmt VARCHAR (5000);
CURSOR get_sessions
IS
SELECT s.sid sid, s.serial# ser
FROM v$session s, v$process p
WHERE s.username = users AND p.addr(+) = s.paddr;
BEGIN
FOR session_rec IN get_sessions
LOOP
BEGIN
stmt := 'ALTER SYSTEM KILL SESSION ''' || session_rec.sid || ',' || session_rec.ser || '''' || ' IMMEDIATE';
--dbms_output.put_line(stmt);
BEGIN
EXECUTE IMMEDIATE stmt;
--EXCEPTION WHEN others THEN
-- dbms_output.put_line('Error killing session: ' || stmt);
-- dbms_output.put_line(SQLERRM);
EXCEPTION
WHEN OTHERS
THEN
-- You probably need to log this error properly here.
-- I will just re-raise it.
CONTINUE;
END;
END;
END LOOP;
END;
/
}
I am doing something like this in a procedure to clear all data from all tables in my database.
LOOP
dbms_utility.exec_ddl_statement('alter table ' || c.owner || '.' || c.table_name || ' disable constraint ' || c.constraint_name);
END LOOP;
.
.
.
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || t.table_name ;
END LOOP;
Now , this throws the following error :
ORA-03291: Invalid truncate option - missing STORAGE keyword
ORA-06512: at "MYSCHEMA.CLEAR_DATA", line 15
ORA-06512: at line 2
Process exited.
Disconnecting from the database MYDB.
Why is a storage keyword mandatory? I thought DROP STORAGE was the default.
Even specifying storage close, as in,
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || t.table_name || 'DROP STORAGE';
doesn't help. The error is the same.
I thought it might have something to do with foreign constraints on some tables. Hence, the 'disable constraint' earlier in the script
I would suggest that you build the command you are executing in a string variable, output it using dbms_output, then execute it. This way you will see exactly what it is trying to execute that is generating the error.
One thing that could be causing this error is if you have a table name with a space in it (yes, it's possible). The solution if that is the case is to wrap the table name in double quotes.
dev> create table "dave exp" (x number);
Table created.
dev> truncate table dave exp;
truncate table dave exp
*
ERROR at line 1:
ORA-03291: Invalid truncate option - missing STORAGE keyword
dev> truncate table "dave exp";
Table truncated.
Change your program:
put your truncate command in a PL/SQL variable prior to execution
add an exception handler that outputs the truncate statements via dbms_output or utl_file (fflush after each one) when you encounter an exception:
LOOP
BEGIN
...
v_sql := 'TRUNCATE TABLE ' || t.table_name ;
EXECUTE IMMEDIATE v_sql;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
dbms_output.put_line(v_sql);
END;
END LOOP;
This should show you the statement causing the issue.
truncate table Table_NAME drop storage;