PL/SQL, how to escape single quote in a string? - oracle

In the Oracle PL/SQL, how to escape single quote in a string ? I tried this way, it doesn't work.
declare
stmt varchar2(2000);
begin
for i in 1021 .. 6020
loop
stmt := 'insert into MY_TBL (Col) values(\'ER0002\')';
dbms_output.put_line(stmt);
execute immediate stmt;
commit;
end loop;
exception
when others then
rollback;
dbms_output.put_line(sqlerrm);
end;
/

You can use literal quoting:
stmt := q'[insert into MY_TBL (Col) values('ER0002')]';
Documentation for literals can be found here.
Alternatively, you can use two quotes to denote a single quote:
stmt := 'insert into MY_TBL (Col) values(''ER0002'')';
The literal quoting mechanism with the Q syntax is more flexible and readable, IMO.

Here's a blog post that should help with escaping ticks in strings.
Here's the simplest method from said post:
The most simple and most used way is to use a single quotation mark with two single quotation marks in both sides.
SELECT 'test single quote''' from dual;
The output of the above statement would be:
test single quote'
Simply stating you require an additional single quote character to print a single quote character. That is if you put two single quote characters Oracle will print one. The first one acts like an escape character.
This is the simplest way to print single quotation marks in Oracle. But it will get complex when you have to print a set of quotation marks instead of just one. In this situation the following method works fine. But it requires some more typing labour.

In addition to DCookie's answer above, you can also use chr(39) for a single quote.
I find this particularly useful when I have to create a number of insert/update statements based on a large amount of existing data.
Here's a very quick example:
Lets say we have a very simple table, Customers, that has 2 columns, FirstName and LastName. We need to move the data into Customers2, so we need to generate a bunch of INSERT statements.
Select 'INSERT INTO Customers2 (FirstName, LastName) ' ||
'VALUES (' || chr(39) || FirstName || chr(39) ',' ||
chr(39) || LastName || chr(39) || ');' From Customers;
I've found this to be very useful when moving data from one environment to another, or when rebuilding an environment quickly.

In my case, I use like this:
stmt := q'!insert into MY_TBL (Col) values('ER0002')!';
Adding: q'! before and !' after string.
This is another reference: Alternative Quoting Mechanism (''Q'') for String Literals

EXECUTE IMMEDIATE 'insert into MY_TBL (Col) values(''ER0002'')'; worked for me.
closing the varchar/string with two pairs of single quotes did the trick. Other option could be to use using keyword, EXECUTE IMMEDIATE 'insert into MY_TBL (Col) values(:text_string)' using 'ER0002'; Remember using keyword will not work, if you are using EXECUTE IMMEDIATE to execute DDL's with parameters, however, using quotes will work for DDL's.

Related

Creating tables in procedure in oracle [duplicate]

In the Oracle PL/SQL, how to escape single quote in a string ? I tried this way, it doesn't work.
declare
stmt varchar2(2000);
begin
for i in 1021 .. 6020
loop
stmt := 'insert into MY_TBL (Col) values(\'ER0002\')';
dbms_output.put_line(stmt);
execute immediate stmt;
commit;
end loop;
exception
when others then
rollback;
dbms_output.put_line(sqlerrm);
end;
/
You can use literal quoting:
stmt := q'[insert into MY_TBL (Col) values('ER0002')]';
Documentation for literals can be found here.
Alternatively, you can use two quotes to denote a single quote:
stmt := 'insert into MY_TBL (Col) values(''ER0002'')';
The literal quoting mechanism with the Q syntax is more flexible and readable, IMO.
Here's a blog post that should help with escaping ticks in strings.
Here's the simplest method from said post:
The most simple and most used way is to use a single quotation mark with two single quotation marks in both sides.
SELECT 'test single quote''' from dual;
The output of the above statement would be:
test single quote'
Simply stating you require an additional single quote character to print a single quote character. That is if you put two single quote characters Oracle will print one. The first one acts like an escape character.
This is the simplest way to print single quotation marks in Oracle. But it will get complex when you have to print a set of quotation marks instead of just one. In this situation the following method works fine. But it requires some more typing labour.
In addition to DCookie's answer above, you can also use chr(39) for a single quote.
I find this particularly useful when I have to create a number of insert/update statements based on a large amount of existing data.
Here's a very quick example:
Lets say we have a very simple table, Customers, that has 2 columns, FirstName and LastName. We need to move the data into Customers2, so we need to generate a bunch of INSERT statements.
Select 'INSERT INTO Customers2 (FirstName, LastName) ' ||
'VALUES (' || chr(39) || FirstName || chr(39) ',' ||
chr(39) || LastName || chr(39) || ');' From Customers;
I've found this to be very useful when moving data from one environment to another, or when rebuilding an environment quickly.
In my case, I use like this:
stmt := q'!insert into MY_TBL (Col) values('ER0002')!';
Adding: q'! before and !' after string.
This is another reference: Alternative Quoting Mechanism (''Q'') for String Literals
EXECUTE IMMEDIATE 'insert into MY_TBL (Col) values(''ER0002'')'; worked for me.
closing the varchar/string with two pairs of single quotes did the trick. Other option could be to use using keyword, EXECUTE IMMEDIATE 'insert into MY_TBL (Col) values(:text_string)' using 'ER0002'; Remember using keyword will not work, if you are using EXECUTE IMMEDIATE to execute DDL's with parameters, however, using quotes will work for DDL's.

How to handle dynamic variable string value in single line

This is my PL/SQL block. When i execute it the result of 'V_QUERY' variable breaks into two lines like:
'%[CDATA[/documents/%/4min.png
/%'.
How can i get it in one line like below: enter image description here
'%[CDATA[/documents/%/4min.png/%'
.
declare
cursor c1 is
select rtrim(ltrim(substr(typesettings, 7), '"'), '"') as typesettings
from trashentry
where rownum < 2;
v_query varchar2(32767);
begin
for r1 in c1
loop
v_query := '''%[CDATA[/documents/%/' || r1.typesettings || '/%''';
dbms_output.put_line(v_query);
end loop;
end;
Most likely you need to trim chr(10) from the end of typesettings. It may not hurt to trim chr(13) as well, on the chance it may be present too.
Assuming there aren't any double-quotes in your input string that you need to keep, you can achieve several things at once: Instead of rtrim(ltrim(...)) (which should be a trim(...) anyway, it does the same thing and is simpler and only calls one function instead of two), you could use translate:
select translate(substr(typesettings, 7), 'x"' || chr(10) || chr(13), 'x') as typesettings
.......
Notice the x in the last two parameters; it doesn't really do anything, it just works around a limitation of the translate function (which in turn is due to Oracle's treatment of empty strings as NULL). In this example, translate will replace every x in the input string with x, and every occurrence of ", chr(10) and chr(13) will be simply deleted.

pl/sql PLS-00201 identifier must be declared

Newbie to PL/SQL. I have several questions, so here's an example of what I'm trying to do.
CREATE OR REPLACE PROCEDURE "my_procedure" (
"my_inparam1" IN VARCHAR2,
"my_inparam2" IN VARCHAR2,
"my_output" OUT SYS_REFCURSOR)
AS
sql_text VARCHAR2 (10000);
BEGIN
sql_text :=
'select something
from my_table
where 1 = 1';
IF '&my_inparam1' <> 'foo'
THEN
sql_text := sql_text || ' and something = 0';
END IF;
IF '&my_inparam1' = 'foo' and '&my_inparam2' = 'bar'
THEN
sql_text := sql_text || ' and somethingelse = 1';
ELSIF '&my_inparam1' = 'foo' AND '&my_inparam2' = 'baz'
THEN
sql_text := sql_text || ' and somethingelse = 0';
END IF;
OPEN my_output FOR sql_text; --ERROR PLS-00201 Identifier 'MY_OUTPUT' must be declared
END;
So obviously I'm trying to return a query result, optionally filtered by whatever parameters I pass in. I'm at a loss as to why the offending line returns an error - in an earlier iteration, I was able to return results, but now, mysteriously, it's stopped working.
1) Is there a better way to approach this?
2) Do I have to reference the input params with the '&my_inparam' syntax?
3) If I do approach this by creating the sql text first and then opening the ref cursor, is there a shortcut for concatening the strings, like
sql_text &= ' and another_condition = 1'
?
In reverse order... no, there is no shorthand for concatenation like &=. You could use the concat() function instead, but the || method is more common, and more convenient especially if you're sticking more than two things together - nested concat() calls aren't as easy to follow. I'd stick with what you're doing.
Secondly, no, you're confusing SQL*Plus substitution variables with PL/SQL variables. Your references to '&my_inparam1' should be my_inparam1, etc; no ampersand and no quotes.
Except for some reason you've decided to make life difficult for yourself and use case-sentisive procedure and variable names, so you have to refer to "my_inparam1", in double quotes, everywhere.
That's why you're getting the message PLS-00201 Identifier 'MY_OUTPUT' must be declared. You didn't quote my_output so by default it's looking for a case-insensitive variable called MY_OUTPUT, which does not exist. It would work if you did this instead:
OPEN "my_output" FOR sql_text;
Unless you have a really really good reason, really don't do that.
CREATE OR REPLACE PROCEDURE my_procedure (
my_inparam1 IN VARCHAR2,
my_inparam2 IN VARCHAR2,
my_output OUT SYS_REFCURSOR)
AS
sql_text VARCHAR2 (10000);
BEGIN
sql_text :=
'select something
from my_table
where 1 = 1';
IF my_inparam1 <> 'foo'
THEN
sql_text := sql_text || ' and something = 0';
END IF;
...
OPEN my_output FOR sql_text;
END;
For more information, refer to the naming rules:
Every database object has a name. In a SQL statement, you represent
the name of an object with a quoted identifier or a nonquoted
identifier.
A quoted identifier begins and ends with double quotation marks (").
If you name a schema object using a quoted identifier, then you must
use the double quotation marks whenever you refer to that object.
A nonquoted identifier is not surrounded by any punctuation.
And more importantly:
Note:
Oracle does not recommend using quoted identifiers for database object names. These quoted identifiers are accepted by
SQL*Plus, but they may not be valid when using other tools that manage
database objects.
You quoted procedure name falls into this category; so do the quoted variable names. They're all identifiers and the same advice applies.

What do the : and ' operators mean

I have to make modifications to an Oracle stored procedure that has the following lines.
InsStmt = 'INSERT INTO EMPLOYEE (Emp_cd, Emp_lst_nm, Emp_fst,nm) VALUES
(:Emp_cd, :Emp_lst_nm, :Emp_fst_nm);';
varExec :='
DECLARE
var1 VARCHAR2(100);
BEGIN
var1 := :Emp_cd||:Emp_lst_nm||:Emp_fst_nm;
'||InsStmt||'
END;';
EXECUTE IMMEDIATE varExec USING ip_param_cd, ip_param_lnm, ip_param_fnm;
I have only basic understanding of Oracle stored procedures. After some research I found out that the || operator is for concatenating strings.
But I'm still wondering what does the below statement mean
var1 := :Emp_cd||:Emp_lst_nm||:Emp_fst_nm;
'||InsStmt||'
I went through the tutorial at http://docs.oracle.com/cd/B28359_01/appdev.111/b28843/tdddg_procedures.htm#CIHGDECD but could not find any help.
Outside of the trigger context, the column : is used to bind variables within a statement.
For example:
EXECUTE IMMEDIATE 'UPDATE mytable SET age = 25 WHERE age = :1'
USING IN localVarAge;
In this case, the :1 value would be replaced by the value of localVarAge.
The order the ':' variables appear in the prepared statement matter, not their actual labels.
In your code there's clearly a piece missing, this part var1 := :Emp_cd||:Emp_lst_nm||:Emp_fst_nm; should be within quotes. That would make sense anyway since you have right after that a closing quote and a concatenation.

Escaping single quote in PLSQL

I want PLSQL to generate strings like:
COMMENT ON COLUMN TABLE.COLUMN IS 'comment from database';
My solution is:
declare
str_comment varchar2(4000);
begin
for rec in (select table_name, column_name, description from description_table)
loop
str_comment:='COMMENT ON COLUMN '||rec.table_name||'.'||rec.column_name||' IS '''||rec.description||'''; ' ;
dbms_output.put_line(str_comment);
end loop;
end;
Output is OK when it doesn't contain single qoutes in rec.description. Otherwise there is need for escape letter. How should I implement it?
OK output line (It's has escape letter to preserve single qoute):
COMMENT ON COLUMN TABLE1.COLUMN1_LV IS 'It''s secret';
NOT NOK output line because no escape letter for single quote added and doesn't compile:
COMMENT ON COLUMN TABLE1.COLUMN1_LV IS 'It's secret';
My solution is not to check if description contains single quotes. I just replace source (description) column's single quote by two single quotes before generating COMMENT ON strings and then I ROLLBACK.
Any better solution?
I do this sort stuff a fair bit (usually generating insert/update statements).
You just need to use the replace function to turn all the ' into ''. i.e. Change it to:
str_comment:='COMMENT ON COLUMN '||rec.table_name||'.'||rec.column_name
||' IS '''||REPLACE( rec.description,'''','''''')||'''; ' ;
You can use the Quote operator like
str_comment:='COMMENT ON COLUMN '||rec.table_name||'.'||rec.column_name||' IS q''[' ||rec.description|| ']'';' ;
see http://psoug.org/reference/string_func.html
Use the REPLACE function in your select.
declare
str_comment varchar2(4000);
begin
for rec in (SELECT table_name, column_name, REPLACE(description, '''', '''''')
FROM description_table)
loop
str_comment:='COMMENT ON COLUMN ' || rec.table_name || '.'
||rec.column_name|| ' IS ''' ||rec.description|| '''; ' ;
dbms_output.put_line(str_comment);
end loop;
end;
You need to use '' in the code
But Before trying it to the actual code ,
try the line which has quotes in the dual
For example:
select '''sumesh''' from dual

Resources