Sed - Fixing an sql insert stament with single quote in value - sql

I am asked to help with a UNIX script that deploys database objects with or without data from 1 machine and/or environment with another. The problem is that some columns have CHAR data with single quotes. Only these single quotes need to be converted to 2 single quotes. I was thinking of using sed or awk, but I can't figure it out. Anyone got any ideas?
example:
INSERT INTO SQL_ERROR_MESSAGE (SQL_Error_Cd,Error_Text) VALUES (5492,'The argument for an INOUT/OUT parameter '%VSTR' is invalid.');
becomes
INSERT INTO SQL_ERROR_MESSAGE (SQL_Error_Cd,Error_Text) VALUES (5492,'The argument for an INOUT/OUT parameter ''%VSTR'' is invalid.');
Thanks for your support.

If you are rather certain about the format of your INSERT statement, this might work for you:
sed "s/\([^']\+'[^']\+\)\('\)\([^']\+\)'\(.*\)/\1\2\2\3\2\2\4/" INPUTFILE
But I'd recommend to check the output :-)
Basically it captures everything till the second(!) ' (in \1), then captures the 2nd ' (\2) - that's not needed, I just wrote it this way ... -, in \3 the string in between the 's which should be escaped, and finally the remaining part of the string (\4), and uses the saved entries in the replacement.
Exapmle output (Linux, GNU sed):
$ sed "s/\([^']\+'[^']\+\)\('\)\([^']\+\)'\(.*\)/\1\2\2\3\2\2\4/"
INPUT LINE #=> INSERT INTO SQL_ERROR_MESSAGE (SQL_Error_Cd,Error_Text) VALUES (5492,'The argument for an INOUT/OUT parameter '%VSTR' is invalid.');
OUTPUT LINE #=> INSERT INTO SQL_ERROR_MESSAGE (SQL_Error_Cd,Error_Text) VALUES (5492,'The argument for an INOUT/OUT parameter ''%VSTR'' is invalid.');

Related

Escape character within single quotes

I'm having an issue figuring out how to ignore signs and variables in a single quote string statement.
I am attempting to update a table with the new text with structure such as:
update xxx
set xxx =
'Our Ref. $BOOKING_NO$
.......
Kind regards'
If your $ chars are being interpreted, it isn't by Oracle ($ isn't special in Oracle anyway, and between single-quotes everything is a string), but rather by your client program or maybe shell script. If, for example, you are running this in SQL*Plus from a Unix-based shell script, you will need to use the appropriate means required by the shell you use to prevent the shell from interpreting $ and ' characters.

Sed script needed to insert LF before each time match in a large single string

I have lengthy string that I need to put a line feed before each instance of a time stamp.
03:38:11,03/07/2017,node,cpu,user,sys,idle,intr/s,ctxt/s,0,0,0,9,91,0,1,0,24,75,0,total,0,17,83,2370,3574,1,0,3,4,
93,1,1,10,4,86,1,total,7,4,89,2922,4653,03:39:11,03/07/2017,node,cpu,user,sys,idle,intr/s,ctxt/s,0,0,4,25,71,0,1,5
,16,79,0,total,4,21,75,2487,3876,1,0,0,3,97,1,1,1,1,98,1,total,1,2,98,2880,4728,03:40:11,03/07/2017,node,cpu,user,
sys,idle,intr/s,ctxt/s,0,0,1,30,69,0,1,1,30,69,0,total,1,30,69,3237,4344,1,0,3,49,47,1,1,10,47,43,1,total,6,48,45,
3920,5702,
I need to see about formatting it as such:
03:38:11,03/07/2017,node,cpu,user,sys,idle,intr/s,ctxt/s,0,0,0,9,91,0,1,0,24,75,0,total,0,17,83,2370,3574,1,0,3,4,93,1,1,10,4,86,1,total,7,4,89,2922,4653,
03:39:11,03/07/2017,node,cpu,user,sys,idle,intr/s,ctxt/s,0,0,4,25,71,0,1,5,16,79,0,total,4,21,75,2487,3876,1,0,0,3,97,1,1,1,1,98,1,total,1,2,98,2880,4728,
03:40:11,03/07/2017,node,cpu,user,sys,idle,intr/s,ctxt/s,0,0,1,30,69,0,1,1,30,69,0,total,1,30,69,3237,4344,1,0,3,49,47,1,1,10,47,43,1,total,6,48,45,3920,5702,
I am currently trying to use the following:
sed -e 's/^[[:digit:]][[:digit:]]\:[[:digit:]][[:digit:]]/\n&/g' cpu.log
The ^ line anchor forces sed to only match the first date stamp. Remove it and you should be fine.
To avoid roplacing the first, maybe massage the script to require something before the match (hard-coding a comma would seem to work, based on your sample data); or just post-process the output to remove the first newline.
sed 's/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/\n&/g'

How to Pass a String with Spaces From Command Line to SQL

I am using command line in Windows 7 to read rows of variables from a CSV, pass those variables into a SQL command, and execute that SQL command for each row in the CSV. This works fine, I believe. Where I am running into trouble is when my variables contain spaces, such as strings that need to be input into my database.
My code looks like this:
Command line:
C:\Users\me>(sqlcmd -S npl-sql01 -d OnBaseTEST -i "C:\Users\me\myquery.sql" -v var1="\Policy Term\Policy\" var2= 'REPORT' var3= 'Commercial' )
Where var1, var2, and var3 are variables in the SQL query that get their values from a CSV.
SQL query:
INSERT INTO testdb (column1, column2, column3)
SELECT $(var1), $(var2), $(var3), od.value
FROM otherdatabase AS od
WHERE od.identifier = 24
When I wrap the variable np in single quotes, the command line chokes up on the space in the path. When I wrap it in double quotes, SQL appears to be treating it as a column name rather than a value to be put into a column (based off of this question). I have also tried wrapping with two sets of quotes, e.g. "'a string'" and '"a string"', with no luck. How should I be writing out this string with spaces so that both command line and SQL can understand it?
Edit: For some reason, removing the trailing variable var3 allows the script to work as intended when the string is wrapped with "'two types of quotes'"

Postgres 9.3 end-of-copy marker corrupt - Any way to change this setting?

I am trying to stream data through an AWK program to a Postgres COPY command. This works great usually. However, in my data recently I have been getting long text stings containing '\.' values.
Postgres Documentation mentions this combination of characters represents the end-of-data marker, http://www.postgresql.org/docs/9.2/static/sql-copy.html, and I am getting the associated errors when trying to insert with COPY.
My question is, is there a way to turn this off? Perhaps change the end-of-data marker to a different combination of characters? Or do I have to alter/remove these strings before trying to insert using the COPY command?
You can try to filter your data through sed 's:\\:\\\\:g' - this would change every \ in your data to \\, which is a correct escape sequence for single backslash in copy data.
But I think not only backslash would be problematic. Also newlines should be encoded by \n, carriage returns as \r and tabs as \t (tab is a default field delimiter in copy).

insert a multiline string in Oracle with sqlplus

I have a SQL script that will insert a long string into a table. The string contains a new line (and this new line is absolutely necessary), so when it is written in a text file, the query is split to multiple lines. Something like:
insert into table(id, string) values (1, 'Line1goesHere
Line2GoesHere
blablablabla
');
This runs ok in Toad, but when I save this as a .sql file and run it using sqlplus, it considers each line a separate query, meaning that each line will fail (beacuse insert into table(id, string) values (1, 'Line1goesHere, Line2GoesHere aren't well-formated scripts.
SP2-0734: unknown command beginning "Line2GoesHere" - rest of line ignored.
Is there a way to fix this?
Enable SQLBLANKLINES to allow blank lines in SQL statements. For example:
SET SQLBLANKLINES ON
insert into table(id, string) values (1, 'Line1goesHere
Line2GoesHere
blablablabla
');
The premise of this question is slightly wrong. SQL*Plus does allow multi-line strings by default. It is only blank lines that cause problems.
You can also use not-well-known feature of Oracle's SQL: Perl style quoted strings.
SQL> select q'[f dfgdfklgdfkjgd
2 sdffdslkdflkgj dglk
3 glfdglkjdgkldj ]'
4 from dual;
Q'[FDFGDFKLGDFKJGDSDFFDSLKDFLKGJDGLKGLFDGLKJDGKLDJ]'
----------------------------------------------------
f dfgdfklgdfkjgd
sdffdslkdflkgj dglk
glfdglkjdgkldj
SQL*Plus Manual
You can end a SQL command in one of three ways:
with a semicolon (;)
with a slash (/) on a line by itself
with a blank line
A blank line in a SQL statement or script tells SQL*Plus that you have
finished entering the command, but do not want to run it yet. Press
Return at the end of the last line of the command.
Turning SQLBLANKLINES on in this situation may be the answer, but even with it you still have to worry about the following SQL*Plus commands.
# ("at" sign) (Start of line)
## (double "at" sign) (Start of line)
# SQLPREFIX (Start of line)
. BLOCKTERMINATOR (Start of line and by itself)
/ (slash) (Start of line and by itself)
; SQLT[ERMINATOR] (Start of line and by itself, or at the end)
SQLPREFIX is something that you cannot turn off; it's a feature of SQL*Plus. BLOCKTERMINATOR can be activated or disabled. Slash on the other hand if it appears at the start of a new line will cause it to execute the contents in the buffer. SQL[TERMINATOR] has a similar behavior.
Another way of inserting newlines to a string is concatenating:
chr(13)||chr(10)
(on windows)
or just:
chr(10)
(otherwise)