I'm currently migrating AIX to Linux. The Oracle script contains a $ in the column name. While fetching through the shell script, I set the escape character to $, but it does not work. The query is like below:
Set escape $
Select c.logoff$time from temp c;
When run from shell script I'm getting "c.logoff invalid identifier".
How can I fix this?
This isn't an SQL*Plus (I assume that's your client) problem, so the set escape isn't doing anything - that's for escaping things SQL*Plus tries to interpret - see the docs.
This is a shell issue/feature. the $time part is being treated as a shell variable, and that doesn't exist, so the final table name doesn't have it. You can escape that at shell level, referring to \$time; e.g. if you're using a heredoc:
sqlplus -s -l usr/pass#db <<EOF
select c.logoff\$time from temp c;
EOF
Related
I can't force KSH to pass \" as a parameter to command.
What I want to be executed LITERALLY is:
command \"foo bar\"
Below examples are executed in ksh with set -x executed beforehand to display the echo of each command in the exact format in which it would be executed (after it is parsed by ksh)
[oracle#localhost sf_vm]$ ksh
$ set -x
What I tried and got is:
$ command \"foo bar\"
+ command '"foo' 'bar"'
not what I need: missing \ and additional ' and "
$ command \\\"foo bar\\\"
+ command '\"foo' 'bar\"'
no luck again: additional ' outside and between foo and bar
$ command "\\\"foo bar\\\""
+ command '\"foo bar\"'
almost right but still unwanted ' on the outside
$ command '\"foo bar\"'
+ command '\"foo bar\"'
again almost right but still ' on the outside
The actual use case is that I'm passing USERID parameter to oracle expdb command in format of
expdp USERID=/ AS SYSDBA which needs to be enclosed in escaped double quotes like so:
expdp USERID=\"/ AS SYSDBA\"
I know I can workaround this by using a prm file for expdp but it's very inconvenient in my case (automated export)
I'm using ksh93 version if that makes any difference:
[oracle#localhost sf_vm]$ ll /etc/alternatives/ksh
lrwxrwxrwx. 1 root root 10 Oct 15 2018 /etc/alternatives/ksh -> /bin/ksh93
Let's start from your use case.
The following command, which you assert works
expdp USERID=\"/ AS SYSDBA\"
evaluates to a rather unintuitive argument list, as you can see below (note that this particular code only works for argument lists that don't contain literal newlines anywhere):
$ printf '%s\n' expdp USERID=\"/ AS SYSDBA\" | jq -Rnc '[inputs]'
["expdp","USERID=\"/","AS","SYSDBA\""]
...which is to say, you're passing expdp three arguments beyond the 0th/first one: USERID="/ is the first argument, AS is the second argument, and SYSDBA" is the third argument. The shell is correct when its set -x implementation prints this argument list as expdp 'USERID="/' AS 'SYSDBA"', as that argument list eval's identically to the above.
Frankly, I doubt very much that this is actually correct/intended usage for any tool. It would make more sense if your backslashes weren't escaped, and your intended usage were instead expdp USERID="/ AS SYSDBA", which would evaluate to (in JSON syntax) ["expdp", "USERID=/ AS SYSDBA"].
Ok, thanks to your comments about the set -x which I did interpreted wrongly I got it actually working with command \"foo bar\" besides what the set output would suggest it correctly passes the "foo bar" enclosed with brackets as a command paramater.
As it turned out my actual issue was the syntax in the parameter value itself.
For future reference following expdp command syntax is correct in ksh when value begin passed has spaces (in this case userid as sysdba):
expdp USERID=\"sys/password#SID as sysdba\" DIRECTORY=EXPDP DUMPFILE=HR.COUNTRIES.dmp TABLES=HR.COUNTRIES ...
Does the db2 -x or db2 -f filename.sql options support use of parameter markers? I am calling a SQL statement from a bash script. I cannot find any optios so far and I think I have to use the string concatenation in bash and pass the SQL to db2 -x which does not look neat.
The DB2 CLP does not support using parameter markers.
However, when you are running db2 non-interactively (i.e., from the shell), you can substitute shell variables:
$ v=4
$ db2 "select count(*) from syscat.tables where card = ${v}"
Because this is just using shell substitution you'll need to handle adding single quotes around your strings (... where tabschema = '${tabschema}' ...), and if your strings have single quotes this becomes more complicated.
You can also use this method in shell scripts in loops:
#!/bin/ksh
db2 connect to sample
for v in 1 2 3 4 5 ; do
db2 "insert into t1 (c1) values (${v})"
done
db2 terminate
This will not help if you're trying to use parameter markers to avoid recompiling the SQL statement every time it's executed, but if you're looking for that you probably want to think about using perl with DBI, ruby/ibm_db, etc.
I have the following which I'm trying to script. I've hit a wall with trying to cater for the mixed quotes as well as asterix.
This is what I have
cmd_1="/usr/local/nz/bin/nzsql -d ${SOURCE_DB} -c "
cmd_2="\"create external table '${EXTERNAL_PATH}${EXTERNAL_FILE}'"
cmd_3=" USING (QUOTEDVALUE 'DOUBLE' ESCAPECHAR '\' DELIM ',' TIMESTYLE '24HOUR' LOGDIR '${EXTERNAL_PATH}' ENCODING 'INTERNAL')"
cmd_4=" as select * from ${SOURCE_TABLE}\""
cmd=${cmd_1}${cmd_2}${cmd_3}${cmd_4}
Which when echo'd looks fine and in fact runs with a copy and paste to the command line.
/usr/local/nz/bin/nzsql -d mydatDba -c "create external table '/datawarehouse/development/externaldata/output/EXT_mytable.csv' USING (QUOTEDVALUE 'DOUBLE' ESCAPECHAR '\' DELIM ',' TIMESTYLE '24HOUR' LOGDIR '/datawarehouse/development/externaldata/output/' ENCODING 'INTERNAL') as select * from mytable"
To get it to echo correctly, I did have to wrap ${cmd} in double quotes and so did the same for the execute which looks like this.
"${cmd}"
When running from the shell script however I receive : No such file or directory. I have verified the directories involved and as I mentioned can actually copy and paste what's generated to the command line and it works fine.
I can only assume that what is being echoed in both my echo command and the error is not actually what's being executed.
Advise on how to get the 'real' command echoed and or on my use of quotes would be greatly appreciated.
Thanks.
Use the built-in eval command:
eval "$cmd"
I have set variables in my .sh file (ex. ENV=$1 RELEASE_ID=$2) within my.sh file. I sqlplus into my sql file like
sqlplus -S $username/password#destination #/path/copysetup/insert.sql
I want to pass variables ENV=$1 RELEASE_ID=$2 calling from a unix prompt into my sql file as
copysetup.sh env01 release 1.0
from my sql file I want to pass the same variable into an oracle table
insert into table...
Can someone assist on how to pass variable from bash shell script to sql file and ultimately insert the into my oracle table?
Pass the parameters on the command line:
sqlplus -S $username/password#destination #/path/copysetup/insert.sql $ENV $RELEASE_ID
then in the SQL script they become &1 and &2 (ensure you have set scan on at the top of the SQL script)
eg
set scan on
insert into foo (env, release) values ('&1', '&2');
commit;
Assuming your insert.sql file is the one which you'd like to insert an environment variable (or any bash variable), you can use sed to find/replace a some placeholder text with your desired value. For instance, if your insert.sql file looked something like
INSERT INTO #mytable VALUES (1,'sometext');
You could use sed to find/replace the #mytable string with the data stored in $MYVAR using the following syntax in a bash script
sed "s/#mytable/$MYVAR" insert.sql > modifiedinsert.sql
Now this would generate a new file, modifiedinsert.sql which you'd then pass into sqlplus.
Please tell me how can i excute an oralce query inside a shell script.I am writing a shell script where I need to execute the oracle queries and scripts inside the shell script.
What is the purpose of these lines
sql_file=sachin.sql
cat <<!SQL > $sql_file
select $1 from dual;
exit;
!SQL
I think they are creating a new file, but what exactly is !SQL
It is the multi-line string terminator (a here-doc). There is no special meaning to the letters used, you could just as well have written !ORACLE, it just denotes that the content of the multi-line string are SQL commands.
What your script does is create a text file called sachin.sql with the contents specified between the two !SQL tokens.
PS: Not sure what shell this is for, my bash does not like the exclamation mark, thinks it is an event.
!SQL is just a token to notify the end of sql statements (here-doc) we can use any token like EOF, ENDSQL anything.
but the pre-requisite is the second token !SQL should start on the first column of the line.