Execute sqlplus command in perl - oracle

I am trying to check sql connection via sqlplus command in perl.
I have used the following code to do this.
print "Befores\n";
$rc=system("sqlplus system/system #sqlfile.sql");
print "After $rc\n";
sleep(10);
The returnes value in rc is 0 this time. But when I give wrong credentials like. The sqlfile.sql file contains the only sql command 'EXIT'.
$rc=system("sqlplus systemabc/system #sqlfile.sql");
This also ends with the return code 0. But, manually doing the Credentials are wrong.
Help me out in solving this...
Thanks in advance. :)

Yes dear friens,,,
It's working fine now.
I just added '\' before #sqlfile.sql, i.e, I escaped the '#' symbol and I mentioned the database name after my password. Now I am getting the perfect output. :)
The change is as bellow:
$rc=system("sqlplus -L system/system#tstdb1 \#sqlfile.sql");
Here the format I used is:
sqlplus -L Uname/Password#DBName \#SqlFileContainingMySQLQuries
And -L Specifies not to reprompt for username or password if the initial connection does not succeed. For more info goto About SQLPLUS
I also tried without escaping the '#' symbol before sqlfile.sql, But the change also should apply for inverted comas, I used Single inverted comas instead of double inverted comas as bellow as mentioned by #René Nyffenegger :
$rc=system('sqlplus -L system/system#tstdb1 #sqlfile.sql');
Here the format I used is:
sqlplus Uname/Password#DBName #SqlFileContainingMySQLQuries
This also works fine.

Yeah... :) I too tried this, Thanks for the answer #user252025
I was doing:
$rc=system("sqlplus -L user/user \#sql_file.sql");
Da rtrn code was wrong for me
Now I ve changed to
$rc=system("sqlplus -L user/user#Mydb \#sql_file.sql");
Its working fine..
Thanks again...

The problem is the line
$rc=system("sqlplus system/system #sqlfile.sql");
You have a string quoted with double quotes ("..."). Such strings try to epxand variables (starting with #, $ and %). Since you have #sqlfile in the string, perl assumes this to be an array (which, of course it is not).
Remedy:
$rc=system('sqlplus system/system #sqlfile.sql');

Why are you doing this? DBI exists to provivide a sane and secure way of using databases and sensibly getting the output/return/errors from them.

Related

How can I update column values with the content of a file without interpreting it?

I need to update values in a column when the row matches a certain WHERE clause, using the content of a text file.
The content of the file is javascript code and as such it may contain single quotes, double quotes, slashes and backslashes - out of the top of my mind, it could contain other special characters.
The content of the file cannot be modified.
This has to be done via psql, since the update is automated using bash scripts.
Using the following command - where scriptName is a previously declared bash variable -
psql -U postgres db<<EOF
\set script $(cat $scriptName.js))
UPDATE table SET scriptColumn=:script WHERE nameColumn='$scriptName';
EOF
returns the following error
ERROR: syntax error at or near "{"
LINE 1: ...{//...
^
I would like to treat the content of the file $scriptName.js as plain text, and avoid any interpretation of it.
You should quote the variable:
UPDATE table SET scriptColumn=:'script' WHERE ...
That causes the contents of the variable to be properly escaped as a string literal.
I found a solution to my problem, even though I don't know why it works.
I leave it here in the hope it might be useful to someone else, or that someone more knowledgeable than me will be able to explain why it works now.
In short, setting the variable as a psql parameter did the trick:
psql -U postgres db -v script="$(cat $scriptName.js)"<<EOF
UPDATE table SET scriptColumn=:'script' WHERE nameColumn='$scriptName'
EOF
Not sure how this differs from
psql -U postgres db <<EOF
\set script "$(cat $scriptName.js)"
UPDATE table SET scriptColumn=:'script' WHERE nameColumn='$scriptName'
EOF
which I tried previously and returns the following error:
unterminated quoted string
ERROR: syntax error at or near "//"
LINE 1: // dummy text blahblah
Thanks to everybody who helped!

sed: properly replace lines containing paths via bash script

I am trying to write a bash script that will do backup-based DUPLICATE database (Oracle) from Production to Development host. One of the steps is to take a copy of the Production database pfile, edit it properly and then power-up a new instance on another host. I am having difficulties to do the following on my bash script:
Production pfile: (single line taken as an example, all others are the same)
*.audit_file_dest='/u01/app/grid/admin/orcl11/adump'
Let's say that the above line should be changed completely to:
*.audit_file_dest='/u02/another/path'
I've had a look at the examples on StackOverflow, but I really can't understand them. Can someone please help me on that?
Many thanks in advance!
EDIT: Thanks a lot guys. This worked out like a charm. Topic Answered.
If it's exactly as you pasted in the question, you can use sed to substitute:
sed -i "s#audit_file_dest='/u01/app/grid/admin/orcl11/adump'#audit_file_dest='/u02/another/path'#" your_file
if you just need to change the single line in your question, #leafei 's line works for you.
if you want to customize your "pfile", like:
change
nameA='oldA'
nameB='oldB'
nameC='oldC'
to
nameA='newA'
nameB='oldB' #here perhaps you want to keep the old value
nameC='newC'
you could try this:
awk 'BEGIN{s="\x27";FS=OFS="="}{if($1=="nameA"){print $1,s"newA"s;next;} if($1=="nameC"){print $1,s"newC"s;next;}}1' pfile
test:
kent$ echo "nameA='oldA'
nameB='oldB'
nameC='oldC'"|awk 'BEGIN{s="\x27";FS=OFS="="}{if($1=="nameA"){print $1,s"newA"s;next;} if($1=="nameC"){print $1,s"newC"s;next;}}1'
nameA='newA'
nameB='oldB'
nameC='newC'

shell scripting quotation

I have written a small script with which I take the name of a File.
#objectname
echo "objectname"
read ON
Can't get simpler.
I do some processing with the file I get.
gpg -c --no-use-agent "$ON"
For example if I have a file a.exe --> It will encrypt it and give me a file with a different md5 and an extension. Now, the file looks this way a.exe.gpg
Now, if I give it a bind the name of the file directly.
like this for example:
Taken from : this link
# This works
fileName='a.exe.gpg'
md5sum=$(md5sum ${fileName})
echo $md5sum
it returns it properly.
What if I want to do it dynamically.
This is what I tried:
#does not work
gpg -c --no-use-agent "$ON"
fileName= `$ON.gpg`
md5sum= $(md5sum ${fileName})
echo $md5sum
I get this bug here: upload.sh: 1: upload.sh: Fire.exe.gpg: not found and the program does not exit.
May I ask where exactly is the mistake I am doing?
The error is here:
fileName= `$ON.gpg`
There should be no space after =. (Also look at the next line.)
You used back-quotes, which execute $ON.gpg rather than simply evaluating it. Back-quotes are the same as $(...) but less elegant. Use double-quotes for this.
Read Greg's wiki entry on quotes for an ultra-detailed explanation with opinionated commentary. :-)
Be careful when making assignments in shell script. Don't use spaces in any sides of the operator=. Try the following:
fileName="$ON.gpg"
md5sum=$(md5sum ${fileName})
Note that the variable and the assignment operator= are together with no space.
Also, when you use backticks as `expression`, it will be executed by shell like using $(expression), as pointed by user ghoti.
You goofed on fixing the filename.
fileName="$ON.gpg"

sqlldr LRM-00112: multiple values not allowed for parameter 'control'

I have a shell script with this code:
sqlldr $ws_usr_eva/$ws_pass_eva#$ws_esq_eva CONTROL=/$HOME/controlfiles/CONTROL_FILE.CTL LOG=/$HOME/batch/log/LOG_FILE.$fecfile.log DATA=/$HOME/batch/input/INPUT_FILE_$fecfile.txt > /$HOME/batch/log/result_loader_eva.ora
The variables $ws_usr_eva, $ws_pass_eva and $ws_esq_eva are filled before I execute the sqlldr. I already check the content and its ok.
So when I run the script, it show me: LRM-00112: multiple values not allowed for parameter 'control'
I tried to run the script without the variables, and it works fine:
sqlldr user/pwd#schema CONTROL=/$HOME/controlfiles/CONTROL_FILE.CTL LOG=/$HOME/batch/log/LOG_FILE.$fecfile.log DATA=/$HOME/batch/input/INPUT_FILE_$fecfile.txt > /$HOME/batch/log/result_loader_eva.ora
I have to use variables in the sqlldr, because it reads them from a configuration file.
I also try with sqlldr userid=$ws_usr_eva/$ws_pass_eva#$ws_esq_eva ... but it didn't work.
Can you help me?
Thanks in advance.
Incase it helps anybody, you need to enclose your paths (data, control, log) in single qoutes. Double qoutes will not work (although sqlldr will not complain, but rather simply ignore the double qoutes).
In your shell, try to escape your variables::
sqlldr "${ws_usr_eva}/${ws_pass_eva}#${ws_esq_eva}" "CONTROL=${HOME}/controlfiles/CONTROL_FILE.CTL" "LOG=${HOME}/batch/log/LOG_FILE.${fecfile}.log" "DATA=${HOME}/batch/input/INPUT_FILE_${fecfile}.txt" > "${HOME}/batch/log/result_loader_eva.ora"

Problem with run commands in shell (bash) with arguments as variables !

(Sorry for the confusion. Previous $ sign occurred when I tried to simplify the actual problem. Thanks for correcting the question)
I wanted to split a directory name on underscores (ex: dir_to_split="my_test_dir") like this:
my_dir=($dir_to_split)
var=$(echo $my_dir | awk -F"_" '{print $1,$2,$3}')
set -- $var
splited_1=$1
splited_2=$2
splited_3=$3
now using these splited_x is causing me errors. ex.
myprograme $splited_1 $splited_2 $splited_3
Can anyone please help me with this ? Thank you....
(Rewritten after updated question.)
What kind of errors do you get? I find it useful to add set -x to the top of my shell scripts when debugging, this lets the shell print all commands it executes so you can pinpoint the line where problems begin.
Are you sure that $dir_to_split is actually set? Does it contain spaces or tabs? Does it contain two underscores? I don't see any other problems right now.
There are in-shell methods of splitting a variable such as:
dir="my_test_dir"
OIFS="$IFS"
IFS="-"
set --
IFS="$OIFS"
See also this SO question.

Resources