I have a process that needs to strip all CRLF from SQL statements and store them with literal characters \r\n and stores this in a .json file. Later, this process is reversed when the .json file is inserted back into the database.
I am using ORACLE 19c.
The original (abbreviated) SQL might look like this:
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME
FROM sztdhof
LEFT JOIN SPRIDEN
ON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM
RIGHT JOIN SSBSECT
ON sztdhof_CRN = SSBSECT_CRN
WHERE spriden_change_ind IS NULL
The resulting string should look like this:
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME\r\nFROM sztdhof\r\nLEFT JOIN SPRIDEN\r\nON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM\r\nRIGHT JOIN SSBSECT\r\nON sztdhof_CRN = SSBSECT_CRN \r\nWHERE spriden_change_ind IS NULL
I have tried numerous ways to get ORACLE REGEXP_REPLACE to recognize the carriage return and line feed together. None seem to work.
To start, I read the value from the db into a variable v_text. Then I attempt the conversion and placing the result into a second variable v_outtext. If I use two separate statements, each works separately. And I can live with that method, but I would like this to work as a single statement. (Note. I have also tried the REPLACE function with similar results.)
This code...
SELECT REPLACE (v_text, chr(13) , '\r\n')
INTO v_outtext
FROM dual;
produces...
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME\r\n
FROM sztdhof\r\n
LEFT JOIN SPRIDEN\r\n
ON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM\r\n
RIGHT JOIN SSBSECT\r\n
ON sztdhof_CRN = SSBSECT_CRN \r\n
WHERE spriden_change_ind IS NULL\r\n
SELECT REGEXP_REPLACE(v_text, chr(10) , '\r\n') --is similar to above, except the \r\n are at the front of each line.
SELECT REGEXP_REPLACE(v_text, (chr(13)chr(10) , '\r\n') gives me an error, missing right parenthesis.
SELECT REGEXP_REPLACE (v_text, '(\r\n)', '\r\n') replaces r with \r and n with \n, but only the first instance.
I have tried numerous iterations. None solve the problem. Any thoughts would be welcome.
You need to concatenate the two characters you want to replace, not just put them in parentheses (even if you supplied both):
SELECT REPLACE(v_text, chr(13) || chr(10) , '\r\n')
INTO v_outtext
FROM dual;
If if it's already in a PL/SQL variable you don't need to to the context switch to select from dual; you can simplify to:
v_outtext := REPLACE(v_text, chr(13) || chr(10) , '\r\n');
but it sounds like you can use the first method to read the value from the database into v_outtext in one go, without the intermediate v_text.
db<>fiddle
Related
This question already has answers here:
How to avoid variable substitution in Oracle SQL Developer
(5 answers)
Closed 3 months ago.
I am trying to query a certain row by name in my sql database and it has an ampersand. I tried to set an escape character and then escape the ampersand, but for some reason this isn't working and I'm uncertain as to what exactly my problem is.
Set escape '\'
select * from V1144engine.T_nodes where node_id in(
select node2_id from V1144engine.T_edges where node1_id in(
select node2_id from V1144engine.T_edges where node1_id in(
select node2_id from V1144engine.T_edges where node1_id =
(select node_id from V1144engine.T_nodes where node_name = 'Geometric Vectors \& Matrices')))
and edge_type_id = 1)
and node_type_id = 1
and node_id in (
select node2_id from V1144engine.T_edges where node1_id =
(select node_id from V1144engine.T_nodes where node_name = 'Algebra II')
and edge_type_id = 2);
Instead of
node_name = 'Geometric Vectors \& Matrices'
use
node_name = 'Geometric Vectors ' || chr(38) || ' Matrices'
38 is the ascii code for ampersand, and in this form it will be interpreted as a string, nothing else. I tried it and it worked.
Another way could be using LIKE and an underline instead the '&' character:
node_name LIKE 'Geometric Vectors _ Matrices'
The chance that you'll find some other record too, which is different in only this one character, is quite low.
Escape is set to \ by default, so you don't need to set it; but if you do, don't wrap it in quotes.
Ampersand is the SQL*Plus substitution variable marker; but you can change it, or more usefully in your case turn it off completely, with:
set define off
Then you don't need to bother escaping the value at all.
You can use
set define off
Using this it won't prompt for the input
straight from oracle sql fundamentals book
SET DEFINE OFF
select 'Coda & Sid' from dual;
SET DEFINE ON
how would one escape it without setting define.
In order to escape & you can try following ways:-
set scan off
set define off
set escape on
then replace & by\&
replace & by &&
One of them should work at least.
additionally if you are using PL/SQL developer then there is & icon in the bottom of SQL window please go there and disable it. Note in the older version this option is not present.
Also make sure set define off is written at the very beginning of the script.
set escape on
... node_name = 'Geometric Vectors \& Matrices' ...
or alternatively:
set define off
... node_name = 'Geometric Vectors & Matrices' ...
The first allows you to use the backslash to escape the &.
The second turns off & "globally" (no need to add a backslash anywhere). You can turn it on again by set define on and from that line on the ampersands will get their special meaning back, so you can turn it off for some parts of the script and not for others.
This works as well:
select * from mde_product where cfn = 'A3D"&"R01'
you define & as literal by enclosing is with double qoutes "&" in the string.
REPLACE(<your xml column>,'&',chr(38)||'amp;')
I wrote a regex to help find and replace "&" within an INSERT, I hope that this helps someone.
The trick was to make sure that the "&" was with other text.
Find “(\'[^\']*(?=\&))(\&)([^\']*\')”
Replace “$1' || chr(38) || '$3”
--SUBSTITUTION VARIABLES
-- these variables are used to store values TEMPorarily.
-- The values can be stored temporarily through
-- Single Ampersand (&)
-- Double Ampersand(&&)
-- The single ampersand substitution variable applies for each instance when the
--SQL statement is created or executed.
-- The double ampersand substitution variable is applied for all instances until
--that SQL statement is existing.
INSERT INTO Student (Stud_id, First_Name, Last_Name, Dob, Fees, Gender)
VALUES (&stud_Id, '&First_Name' ,'&Last_Name', '&Dob', &fees, '&Gender');
--Using double ampersand substitution variable
INSERT INTO Student (Stud_id,First_Name, Last_Name,Dob,Fees,Gender)
VALUES (&stud_Id, '&First_Name' ,'&Last_Name', '&Dob', &&fees,'&gender');
I know it sucks. None of the above things were really working, but I found a work around. Please be extra careful to use spaces between the apostrophes [ ' ], otherwise it will get escaped.
SELECT 'Hello ' '&' ' World';
Hello & World
You're welcome ;)
I have the following SQL code
SELECT State.CODE Code,
State.CODE1 Code1,
State.CODE2 Code2,
YYY.1003."BRANCH" "Branch"
FROM XXX.1002 State
LEFT JOIN YYY.1003
ON State.CODE= YYY.1003.CODE
Now I need a new column that shows me the field/ column "Country" from table ZZZ.100.
The key is 1002.CODE1 - ZZZ.100.CODE1
Unfortunately, ZZZ.100.CODE1 has spaces before the values (4 spaces).
How can I use the trim function (is this the right one) to get a join on 1002.CODE1 - ZZZ.100.CODE1
It looks like you want:
select x.code, x.code1, x.code2, y.branch, z.country
from xxx.1002 x
left join yyy.1003 y on x.code= y.code
left join zzz.100 z on trim(z.code1) = x.code1
trim() removes spaces on both ends of the string. If you want to remove only leading spaces, you can do: trim(leading ' ' from z.code1).
Note that I used more meaningful table aliases, in order to make the query easier to write and read.
I would also reommend against using all-digits table names: in Oracle, non-quoted identifiers must begin begin with an alphabetic character.
First thing is why a Key column contains spaces on it? A key column should never contain spaces, it is terrible for performance.
The point to think about here is to remove those spaces from this column
The use of TRIM, considering you are using SQL Server
In SQL Server you can use LTRIM (for left trim, remove left spaces) and/or RTRIM (for right trim, remove right spaces)
Ex:
Select
LTRIM(RTRIM(Table.Column))
from Table
I hope this can help you
I'm writing a query that returns a bunch of things from multiple tables. The main query is against Table_1. I need to return a substring from a field in table 7. But I'm getting an error that Substring_Index is an invalid identifier. How can I achieve the intended result?
I have a field COLUMN_1 of TABLE_1 that has 3+ pieces of data, separated by " : " (space colon space) and I need to strip out the text before the first delimiter, and return the rest of it (regardless of length).
A simplified example:
SELECT t1.name
,t1.address
,t1.phone
,t2. fave_brand
,SUBSTRING_INDEX(t3.fave_product, ' : ', -1) AS Fave Product
FROM table_1 t1
INNER JOIN table_2 t2
ON t2.brand_SK = t1.fave_brand_FK
INNER JOIN table_3 t3
ON t3.product_list_SK = t1.fave_products
WHERE <a series of constraints>;
Please note, I am NOT normally an SQL developer, but the back-end dev is on vacation and I've been tasked with cobbling this fix together. I'm a beginner at best.
In oracle you could use regexp_replace():
regexp_replace(t3.fave_product, '^[^:]*:', '') "Fave Product"
regexp_replace() replaces the part of the string that matches the regexp given as second argument with the value given as third argument. Here, we use the empty string as third argument, meaning that the matching part of the string is suppressed.
Regexp breakdown:
^ beginning of the string
[^:]* as many characters as possible other than ":" (possibly, 0 characters)
: character ":"
NB: identifiers that contain special characters (such as space) need to be double quoted.
Oracle does not support substring_index(). That is a MySQL function.
You can use regexp_substr(). Without sample data it is a little hard to be 100% sure, but I think the logic you want is:
regexp_substr(t3.fave_product, '[^:]+$') as fave_product
I am attempting to generate a new field based on an existing field where some of the entries contain different special characters. (ie. *, ') The special characters are at the end of the string, which is either second or third position.
I am NEW to SQL but not new to data. I am using a CASE WHEN statement. I have tried several approaches and several other commands within the CASE statement.
what I want is:
SELECT *
CASE WHEN grde_code_mid LIKE '[*]' THEN 'Remedial'
WHEN grde_code_mid LIKE '[']' THEN 'Continuing'
ELSE NULL
END AS class_type
FROM grde_tble
I keep getting the same error: "FROM keyword not found where expected". I expect to have all 3 returns in the new field.
If you're looking for ' character you should escape it.
Change
WHEN grde_code_mid LIKE '[']' THEN 'Continuing'
by
WHEN grde_code_mid LIKE '['']' THEN 'Continuing'
Have a look at this question: How do I escape a single quote in SQL Server?
There are several issues with your query:
you are missing a comma in the SELECT clause between * and the CASE expression (this is causing the error that you are currently getting)
the bracket notations is only supported in SQL-Server; if you want to match on strings that end with * in a portable manner, you need expression ... LIKE '%*', not LIKE '[*]'
single quotes embedded in a string need to be escaped
SELECT *, other_field FROM ... is not supported on all RDBMS (and, as commented by jarhl, actually isn't standard ANSI SQL notation); you usually need to prefix the * with the table name or alias
Consider:
SELECT
g.*,
CASE
WHEN grde_code_mid LIKE '%*' THEN 'Remedial'
WHEN grde_code_mid LIKE '%''' THEN 'Continuing'
ELSE NULL
END AS class_type
FROM grde_tble g
Thank you all. I am still getting the hang of the language and proper terms. I am using Oracle DB. Also, yes, I did need to reference the table in the select statement (SELECT tablename.*). Found a work around:
CASE WHEN regexp_like(grde_code_mid, '[*]') THEN 'Remedial'
WHEN regexp_like(grde_code_mid, '['']') THEN 'Continuing'
ELSE NULL END AS special_class
I want to remove semicolons and create new columns to separate the years with different columns in this table:
I tried to replace it with the following code but I had this result:
This result only deletes what comes after the first semicolon and does not replace subsequent semicolons with new columns with the years, thanks for the answers:
SELECT Province, REPLACE( Annee_Guerre, ';' , CHR(13) + CHR(10))
FROM Feuil1;
You might want to consider replacing the ";" with vbCrLf in the VBA code using a recordset and a loop. Queries usually do not respond well to Cr and Lf in the strings.