How do I ignore ampersands in a SQL script running from SQL Plus? - sql

I have a SQL script that creates a package with a comment containing an ampersand (&). When I run the script from SQL Plus, I am prompted to enter a substitute value for the string starting with &. How do I disable this feature so that SQL Plus ignores the ampersand?

This may work for you:
set define off
Otherwise the ampersand needs to be at the end of a string,
'StackOverflow &' || ' you'
EDIT: I was click-happy when saving... This was referenced from a blog.

If you sometimes use substitution variables you might not want to turn define off. In these cases you could convert the ampersand from its numeric equivalent as in || Chr(38) || or append it as a single character as in || '&' ||.

I resolved with the code below:
set escape on
and put a \ beside & in the left 'value_\&_intert'
Att

You can set the special character, which is looked for upon execution of a script, to another value by means of using the SET DEFINE <1_CHARACTER>
By default, the DEFINE function itself is on, and it is set to &
It can be turned off - as mentioned already - but it can be avoided as well by means of setting it to a different value. Be very aware of what sign you set it to. In the below example, I've chose the # character, but that choice is just an example.
SQL> select '&var_ampersand #var_hash' from dual;
Enter value for var_ampersand: a value
'AVALUE#VAR_HASH'
-----------------
a value #var_hash
SQL> set define #
SQL> r
1* select '&var_ampersand #var_hash' from dual
Enter value for var_hash: another value
'&VAR_AMPERSANDANOTHERVALUE'
----------------------------
&var_ampersand another value
SQL>

set define off <- This is the best solution I found
I also tried...
set define }
I was able to insert several records containing ampersand characters '&' but I cannot use the '}' character into the text
So I decided to use "set define off" and everything works as it should.

According to this nice FAQ there are a couple solutions.
You might also be able to escape the ampersand with the backslash character \ if you can modify the comment.

I had a CASE statement with WHEN column = 'sometext & more text' THEN ....
I replaced it with
WHEN column = 'sometext ' || CHR(38) || ' more text' THEN ...
you could also use
WHEN column LIKE 'sometext _ more text' THEN ...
(_ is the wildcard for a single character)

Related

escape in a select statement

In the following sql, what the use of escape is ?
select * from dual where dummy like 'funny&_' escape '&';
SQL*Plus ask for the value of _ whether escape is specified or not.
The purpose of the escape clause is to stop the wildcard characters (eg. % or _) from being considered as wildcards, as per the documentation
The reason why you're being prompted for the value of _ is because you're using &, which is also usually the character used to prompt for a substitution variable.
To stop the latter from happening, you could:
change to a different escape character
prior to running your statement, run set define off if you're using SQL*Plus (or as a script in a GUI, eg. Toad) or turn off the substitution variable prompting if you're using a GUI.
change the define character to something different by running set define <character>
The escape character is used to indicate that the underscore should be matched as an actual character, rather than as a single-character wildcard. This is explained in the documentation.
You can include the actual characters % or _ in the pattern by using the ESCAPE clause, which identifies the escape character. If the escape character precedes the character % or _ in the pattern, then Oracle interprets this character literally in the pattern rather than as a special pattern-matching character.
If you didn't have the escape clause then the underscore would match any single character, so where dummy like 'funny_' would match 'funnyA', 'funnyB', etc. and not just an actual underscore.
The escape character you've chosen is & which is the default SQL*Plus client substitution variable marker. It has nothing to do with the escape clause, and using that is causing the &_ part of the pattern to be interpreted as a substitution variable called _, hence your being prompted. As it isn't related, the escape clause has no effect on that.
The simplest thing is probably to choose a different escape character. If you want to use that specific escape character and not be prompted, disable or change the substitution character:
set define off
select * from dual where dummy like 'funny&_' escape '&';
set define on
That will then match rows where dummy contains exactly the string 'funny_'. (It's therefore equivalent to where dummy = 'funny_', as there are no unescaped wildcards, making the like pattern matching redundant). It will not match any that start with that pattern (it's sort of like using regexp_like with start and end anchors, and you might be expecting it to work as if you hadn't supplied anchors, but it doesn't). You would need to add a % wildcard for that:
set define off
select * from dual where dummy like 'funny&_%' escape '&';
set define on
And if you want to match any that don't start with funny_ but have it somewhere in the middle of the value, you would need to add another wildcard before it too:
set define off
select * from dual where dummy like '%funny&_%' escape '&';
set define on
You haven't shown any sample data or expected results to it isn't clear which pattern you need.
SQL Fiddle doesn't have substitution variables but here's an example showing how those three patterns match various values.
The syntax for the SQL LIKE Condition is:
expression LIKE pattern [ ESCAPE 'escape_character' ]
Parameters or Arguments
expression : A character expression such as a column or field.
pattern : A character expression that contains pattern matching. The patterns that you can choose from are:
Wildcard | Explanation
---------+-------------
% | Allows you to match any string of any length (including zero length)
_ | Allows you to match on a single character
escape_character: Optional. It allows you to test for literal instances of a wildcard character such as % or _.
Source : http://www.techonthenet.com/sql/like.php

Remove Special Characters from an Oracle String

From within an Oracle 11g database, using SQL, I need to remove the following sequence of special characters from a string, i.e.
~!##$%^&*()_+=\{}[]:”;’<,>./?
If any of these characters exist within a string, except for these two characters, which I DO NOT want removed, i.e.: "|" and "-" then I would like them completely removed.
For example:
From: 'ABC(D E+FGH?/IJK LMN~OP' To: 'ABCD EFGHIJK LMNOP' after removal of special characters.
I have tried this small test which works for this sample, i.e:
select regexp_replace('abc+de)fg','\+|\)') from dual
but is there a better means of using my sequence of special characters above without doing this string pattern of '\+|\)' for every special character using Oracle SQL?
You can replace anything other than letters and space with empty string
[^a-zA-Z ]
here is online demo
As per below comments
I still need to keep the following two special characters within my string, i.e. "|" and "-".
Just exclude more
[^a-zA-Z|-]
Note: hyphen - should be in the starting or ending or escaped like \- because it has special meaning in the Character class to define a range.
For more info read about Character Classes or Character Sets
Consider using this regex replacement instead:
REGEXP_REPLACE('abc+de)fg', '[~!##$%^&*()_+=\\{}[\]:”;’<,>.\/?]', '')
The replacement will match any character from your list.
Here is a regex demo!
The regex to match your sequence of special characters is:
[]~!##$%^&*()_+=\{}[:”;’<,>./?]+
I feel you still missed to escape all regex-special characters.
To achieve that, go iteratively:
build a test-tring and start to build up your regex-string character by character to see if it removes what you expect to be removed.
If the latest character does not work you have to escape it.
That should do the trick.
SELECT TRANSLATE('~!##$%sdv^&*()_+=\dsv{}[]:”;’<,>dsvsdd./?', '~!##$%^&*()_+=\{}[]:”;’<,>./?',' ')
FROM dual;
result:
TRANSLATE
-------------
sdvdsvdsvsdd
SQL> select translate('abc+de#fg-hq!m', 'a+-#!', etc.) from dual;
TRANSLATE(
----------
abcdefghqm

How to escape value in parameter passed to Oracle SQL script

I have an sql script which is executed using sql plus. It reads input parameters and the beginning looks like this:
SET DEFINE ON
DEFINE PARAM1 = '&1'
DEFINE PARAM2 = '&2'
DECLARE
...
Now I would like to use this script with the parameters, but I need to use some special characters, particularly '
##./update.sql 'value of first param' 'Doesn't work'
^
--------------------------------------------| Here's the problem
commit;
When I do the usual way of concatenation strings like this:
'Doesn'||chr(39)||'t work'
only Doesn appear in the PARAM2. Is there some way to escape the character in a way that the sqlplus will read it as a single string?
You need to use escape characters to achieve this.
{} Use braces to escape a string of characters or symbols. Everything within a set of braces in considered part of the escape sequence. When you use braces to escape a single character, the escaped character becomes a separate token in the query.
\ Use the backslash character to escape a single character or symbol. Only the character immediately following the backslash is escaped.
Some examples on single character escape
SELECT 'Frank''s site' AS text FROM DUAL;
TEXT
--------------------
Franks's site
Read more here
For escaping & in SQL*Plus
SET ESCAPE '\'
SELECT '\&abc' FROM dual;
OR
SET SCAN OFF
SELECT '&ABC' x FROM dual;
Escaping wild card
SELECT name FROM emp
WHERE id LIKE '%/_%' ESCAPE '/';
SELECT name FROM emp
WHERE id LIKE '%\%%' ESCAPE '\';
From a shell you should call the script like that:
sqlplus user#db/passwd #update 'value of first param' "Doesn't work"
(the word #update refer to your script which is named update.sql)
Then you have to use literal quoting in your script:
DEFINE PARAM2 = q'[&2]';
Documentation for literals can be found here.

DB2/iSeries SQL clean up CR/LF, tabs etc

I need to find and clean up line breaks, carriage returns, tabs and "SUB"-characters in a set of 400k+ string records, but this DB2 environment is taking a toll on me.
Thought I could do some search and replacing with the REPLACE() and CHR() functions, but it seems CHR() is not available on this system (Error: CHR in *LIBL type *N not found). Working with \t, \r, \n etc doesn't seem to be working either. The chars can be in the middle of strings or at the end of them.
DBMS = DB2
System = iSeries
Language = SQL
Encoding = Not sure, possibly EBCDIC
Any hints on what I can do with this?
I used this SQL to find x'25' and x'0D':
SELECT
<field>
, LOCATE(x'0D', <field>) AS "0D"
, LOCATE(x'25', <field>) AS "25"
, length(trim(<field>)) AS "Length"
FROM <file>
WHERE LOCATE(x'25', <field>) > 0
OR LOCATE(x'0D', <field>) > 0
And I used this SQL to replace them:
UPDATE <file>
SET <field> = REPLACE(REPLACE(<field>, x'0D', ' '), x'25', ' ')
WHERE LOCATE(x'25', <field>) > 0
OR LOCATE(x'0D', <field>) > 0
If you want to clear up specific characters like carriage return (EBCDIC x'0d') and line feed (EBCDIC x'25') you should find the translated character in EBCDIC then use the TRANSLATE() function to replace them with space.
If you just want to remove undisplayable characters then look for anything under x'40'.
Here is an sample script that replaces X'41' by X'40'. Something that was creating issues at our shop:
UPDATE [yourfile] SET [yourfield] = TRANSLATE([yourfield], X'40',
X'41') WHERE [yourfield] like '%' concat X'41' concat '%'
If you need to replace more than one character, extend the "to" and "from" hexadecimal strings to the values you need in the TRANSLATE function.
Try TRANSLATE or REPLACE.
The brute force method involves using POSITION to find the errant character, then SUBSTR before and after it. CONCAT the two substrings (less the undesirable character) to re-form the column.
The character encoding is almost certainly one of the EBCDIC character sets. Depending on how the table got loaded in the first place, the CR may be x'0d' and the LF x'15', x'25'. An easy way to find out is to get to a green screen and do a DSPPFM against the table. Press F10 then F11 to view the table is raw, hexadecimal (over/under) format.
For details on the available functions see the
DB2 for i5/OS SQL Reference.
Perhaps the TRANSLATE() function will serve your needs.
TRANSLATE( data, tochars, fromchars )
...where fromchars is the set of characters you don't want, and tochars is the corresponding characters you want them replaced with. You may have to write this out in hex format, as x'nnnnnn...' and you will need to know what character set you are working with.
Using the DSPFFD command on your table should show the CCSID of your fields.
we struggled a lot to replace the new line char and carriage return from flat file.
Finally we used below sql to sort the issue.
REPLACE(REPLACE(COLUMN_NAME, CHR(13), ''), CHR(10), '')
Try it out
CR = CHR(13)
LF = CHR(10)

How to insert a string which contains an "&"

How can I write an insert statement which includes the & character? For example, if I wanted to insert "J&J Construction" into a column in the database.
I'm not sure if it makes a difference, but I'm using Oracle 9i.
I keep on forgetting this and coming back to it again! I think the best answer is a combination of the responses provided so far.
Firstly, & is the variable prefix in sqlplus/sqldeveloper, hence the problem - when it appears, it is expected to be part of a variable name.
SET DEFINE OFF will stop sqlplus interpreting & this way.
But what if you need to use sqlplus variables and literal & characters?
You need SET DEFINE ON to make variables work
And SET ESCAPE ON to escape uses of &.
e.g.
set define on
set escape on
define myvar=/forth
select 'back\\ \& &myvar' as swing from dual;
Produces:
old 1: select 'back\\ \& &myvar' from dual
new 1: select 'back\ & /forth' from dual
SWING
--------------
back\ & /forth
If you want to use a different escape character:
set define on
set escape '#'
define myvar=/forth
select 'back\ #& &myvar' as swing from dual;
When you set a specific escape character, you may see 'SP2-0272: escape character cannot be alphanumeric or whitespace'. This probably means you already have the escape character defined, and things get horribly self-referential. The clean way of avoiding this problem is to set escape off first:
set escape off
set escape '#'
If you are doing it from SQLPLUS use
SET DEFINE OFF
to stop it treading & as a special case
An alternate solution, use concatenation and the chr function:
select 'J' || chr(38) || 'J Construction' from dual;
The correct syntax is
set def off;
insert into tablename values( 'J&J');
There's always the chr() function, which converts an ascii code to string.
ie. something like:
INSERT INTO
table
VALUES (
CONCAT( 'J', CHR(38), 'J' )
)
You can insert such an string as 'J'||'&'||'Construction'.
It works fine.
insert into table_name (col_name) values('J'||'&'||'Construction');
INSERT INTO TEST_TABLE VALUES('Jonhy''s Sport &'||' Fitness')
This query's output : Jonhy's Sport & Fitness
SET SCAN OFF is obsolete
http://download-uk.oracle.com/docs/cd/B10501_01/server.920/a90842/apc.htm
In a program, always use a parameterized query. It avoids SQL Injection attacks as well as any other characters that are special to the SQL parser.
I've found that using either of the following options works:
SET DEF OFF
or
SET SCAN OFF
I don't know enough about databases to know if one is better or "more right" than the other. Also, if there's something better than either of these, please let me know.
SET ESCAPE ON;
INSERT VALUES("J\&J Construction") INTO custnames;
(Untested, don't have an Oracle box at hand and it has been a while)
If you are using sql plus then I think that you need to issue the command
SET SCAN OFF
Stop using SQL/Plus, I highly recommend PL/SQL Developer it's much more than an SQL tool.
p.s. Some people prefer TOAD.
Look, Andrew:
"J&J Construction":
SELECT CONCAT('J', CONCAT(CHR(38), 'J Construction')) FROM DUAL;