How to handle dynamic variable string value in single line - oracle

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.

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.

Oracle PL/SQL - wildcard replacements with empty strings

To give you a little heads up. I am fairly new to the PL/SQL world.
Most of the text below is just to give you a little context.
Also, I have to use a function to generate the text on the fly. It is not an option to write the text into the db.
Anyway, I am working on a set of functions that will generate strings.
function f_nlg_concat(p_id in number) return varchar2 as
l_id number;
l_text_schaden varchar2(4000);
begin
l_id := p_id;
l_text := f_nlg(l_id);
l_text := f_nlg_replace(l_text, l_id);
end;
The above function is the one that concatinates all the strings. For this example I will only use one text (l_text). The l_text will be provided by the function:
f_nlg(p_id)
Now where it gets interesting is the second function:
f_nlg_replace(p_text,p_id)
This function basically queries via dynamic sql to find the right replacements for the wildcard. There are alot of wildcards.
A text might look like:
'I am a text with this <wildcard>.'
A view provides the right wildcard replacement. I am able to identify the right replacement by iterating over all the columns of the view by using this dynamic sql:
for cur in (SELECT atc.column_name
FROM all_tab_cols atc
WHERE lower(table_name) like 'v_nlg_wildcards'
AND owner = 'ME') loop
/*check if exist*/
l_query1 := 'select count(' || cur.column_name ||
') from ME.v_nlg_wildcards nw where nw.id =' ||
l_id;
execute immediate l_query1
into l_wildcard;
if l_wildcard = 1 then
l_query2 := 'select ' || cur.column_name ||
' from ME.v_nlg_wildcard nw where nw.id =' ||
l_id;
execute immediate l_query2
into l_baustein;
/*THIS IS WHERE I GOT A QUESTION*/
l_text := replace(l_text,
'<' || lower(cur.column_name) || '>',
l_wildcard);
else
continue;
end if;
end loop;
It works all perfect as long as there are wildcards to find. I case there is a NULL the replace wont work obviously.
But have you had any familiar cases in where you had to replace wildcards with empty strings?
Any ideas on how to still do the replacements?
So that there'll be no wildcards left in the text.
The whole text should still look like there is not wildcard left. The sentences are partly written that an empty replacement would fit as well.
Thank y'all in advance.
Cheers,
Sven

oracle open cursor with string variable gives me errors

I have problems with opening cursor with string variable
here is my oracle database code
FUNCTION f_get_cursor(p_date_to_forecast VARCHAR) RETURN SYS_REFCURSOR AS
v_cursor SYS_REFCURSOR;
v_groupby_stmt VARCHAR(200) := 'GROUP BY '
|| CASE WHEN p_date_to_forecast = 'HOLIDAY' THEN
'DAY, ' ELSE '' END
|| 'TNI, FRMP, LR, HH;';
v_select_stmt VARCHAR2(1000) := 'SELECT WEEKDAY, TNI, FRMP, LR, HH,
AVG(Coalesce(VOLUME, 0)) AS AverageVolume
FROM (SELECT v.TNI, v.FRMP, v.LR, v.DAY,
v.HH, v.VOLUME, CASE WHEN
hd.HOLIDAY_DATE is not null
then ''HOLIDAY''
ELSE trim(to_char(v.DAY, ''Day''))
END AS WEEKDAY
FROM v_nem_rm16 v
LEFT JOIN DBP_ADMIN.DBP_HOLIDAY hd
ON v.DAY = hd.HOLIDAY_DATE
WHERE v.STATEMENT_TYPE !=''FORCAST'')
WHERE WEEKDAY = ''' || p_date_to_forecast
|| '''' || ' ' || v_groupby_stmt;
BEGIN
OPEN v_cursor FOR v_select_stmt;
return v_cursor;
END;
I am just trying to open cursor based on the parameter "p_date_to_forcast", which is just string of the name of the week like "Saturday, Tuesday..and so on" and return the cursor.
When I run the query, I got this error
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than
letters and numbers. $#_ are also allowed after the first
character. Identifiers enclosed by doublequotes may contain
any character other than a doublequote. Alternative quotes
(q'#...#') cannot use spaces, tabs, or carriage returns as
delimiters. For all other contexts, consult the SQL Language
Reference Manual.
*Action:
What is the problem and How can I fix it???
thanks
Have you tried this
for r_cur in your_cursor_name(Your_parameter) Loop
-- your working --
End loop;

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.

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