Launch PL/SQL script from batch file (with arguments) - batch-file

I'm strugling at passing arguments to a PL/SQL script from a Windows .bat file.
Here is the content of the batch file :
#echo off
set mName = "test"
exit | sqlplus <connection_string> #test.sql %mName%
pause
And here is the content of test.sql :
set verify off
set serveroutput on size unlimited
BEGIN
DBMS_OUTPUT.PUT_LINE('&&1');
END;
/
I would expect to see "test" appearing in the shell but instead, I get the following message :
Enter value for 1:
SP2-0546: User requested Interrupt or EOF detected.
Does anyone have a solution to this problem ?

Remove the spaces around your = sign. Here's my working batch file:
#echo off
set mName="test"
exit | sqlplus <connection_string> #test.sql %mName%
pause
Also note that you can use the -L option on sqlplus for batch jobs:
-L Attempts to log on just once, instead of reprompting on error.

Related

how to concatenate two variables when one has spaces in it in AzureDevops batch file

I have this input in my ps script. I am passing $(Build.ArtifactStagingDirectory) system variable to get the path in the input %1. The path has spaces i.e. E:\Build Agents\Agent2\_work\15\a. I need to concatenate this with other path but I am not able to do so.
set BuildDrop=%1
set Directory=%BuildDrop% + "\adapters\bin"
This is my output, which is incorrect as Directory should be something like E:\Build Agents\Agent2\_work\15\a\adapters\bin. How to solve this?
set BuildDrop="E:\Build Agents\Agent2\_work\15\a"
set Directory="E:\Build Agents\Agent2\_work\15\a" + "\adapters\bin"
My task is like this in my build pipeline
Task : Batch script
Description : Run a Windows command or batch script and optionally allow it to change the environment
Version : 1.1.10
I found the solution for this. Since my %1 had space I needed to remove apostrohphe before assigning. I did it using ~ variable. working code looks like this.
set "BuildDrop=%~1"
set "Directory=%BuildDrop%\adapters\bin"
You could try this :
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
echo %Directory%
Sample Output
This is the concatenation code.
%BuildDrop%\adapters\bin
In my above sample I am trying to concatenate C:\Users\svijay\Desktop & \adapters\bin using the batch script
And the output : C:\Users\svijay\Desktop\adapters\bin
UPDATE :
#echo off
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
set Directory= %Directory:"=%
echo %Directory%
If you have space, you could provide the "" to provide input.
In your code you could remove the double quotes.
%Directory:"=% - Removes the Double quotes from the string literal.
Sample output :
You may use this to create Azure DevOps variable containing your path
powershell: |
$directory = $(Build.ArtifactStagingDirectory)
$newDirectory = $directory + "\adapters\bin"
Write-Host "##vso[task.setvariable variable=testvar]$newDirectory "
and if you need set variable in powershell script
$BuildDrop=$args[0]
$Directory=$BuildDrop + "\adapters\bin"
Here you have an article how to use parameters in powershell.
We can use powershell task in the Azure DevOps to concatenate two variables.
Sample:
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)"
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)\adapters\bin"
Result:
In addition, I found a similar issue, please also check it.
Update1
Use power shell script in the Azure DevOps pipeline
$testpath1 = "E:\Build Agents\Agent2\_work\15\a"
$testpath2 = "\adapters\bin"
Write-Host "path is $($testpath1)$($testpath2)"
Result:
Use local power shell
Result:
Update2
.bat file
set testpath1=E:\Build Agents\Agent2\_work\15\a
set testpath2=\adapters\bin
set newpath=%testpath1%%testpath2%
echo %newpath%
Pipeline result:

Oracle sqlplus > substitution a prompt variable

I have a *.sql script file and there are some PROMPT commands in this file which force user to type in something.
I would like to execute this script file with sqlplus and supress the prompt question somehow.
Is there any way to supress the question and substitute its value with a pre-defined variable?
This is my test code:
set define on
set define $
SET VERIFY OFF
SET HEADING OFF
DEFINE semaowner = "hello" (CHAR);
accept semaowner prompt "schema owner: "
select '$semaowner' semaowner from dual;
quit;
And the way how I execute it:
sqlplus sys/ora123#host:port/schema as sysdba #prompt-demo.sql
But it does not work because the prompt appears either the DEFINE command is applied or not.
You could supply the response to the prompt from the command line, wrapped in a shell script/batch file if necessary:
echo schema_name | sqlplus sys/ora123#host:port/schema as sysdba #prompt-demo.sql
That works on Windows and Linux.
So you can do that in dev with (presumably) a fixed known value; and in prod just run it as you were before and have to manually enter the value.
You will still see the prompt text in dev, but it won't stop and wait for input.
If you have multiple prompts you could use multiple echos:
(echo schema_name && echo something_else) | sqlplus ...
which also works in both; in Linux you could also use a single print statement with embedded newlines:
print "schema_name\nsomething_else\n" | sqlplus ...
or a heredoc:
sqlplus sys/ora123#host:port/schema as sysdba #prompt-demo.sql <<!EOF
schema_name
something_else
!EOF
but that doesn't help you on your Windows dev box. (There may be a heredoc equivalent on Windows but I think it's basically rearranging the echos...)

How do I execute SQL commands using a batch (.bat) file without accessing external SQL?

Is it possible to execute SQL commands written in a batch (.bat) file without accessing an external SQL script file. How can I do that? I don't want to call an external sql because i want to require as input a month, then execute the sql command that contains that month in some queries.
Asuume you have 3 files in your folder.
file 1 => .sql file
file 2 => mybatchfile1.bat(which has sqlcmds or cmd to execute the above .sql file)
file 3 => one other batch file(myexecute.bat) to call the above batch file(which has content "start mybatchfile1.bat")
All you need to create is myexecute.bat with the below content:
start mybatchfile1.bat
or
call mybatchfile1.bat
You can use either start or call.
Recomend on using powershell script:
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "SERVER\Instance" -Password "Password"
the output will be orginized as a Table and it's far more easy then bat file
Yes, you can run a query from a single DOS batch script, getting input from command line parameters and/or user prompts, rather easily. SQLCMD allows for passing in a query on the command line. By the very nature of passing something into a program from the command line, you can just place the DOS variable wherever you want it to go.
Place the following into a script with an extension of .cmd (you should not be using the .bat extension unless you have a specific need for something to run in a 16-bit process):
#ECHO OFF
ECHO.
SET /P Month="Please enter in a month: "
ECHO.
ECHO.
ECHO Month = %Month%
ECHO.
SET Month=%Month:'=%
ECHO Month with single-quotes removed = %Month%
ECHO.
SQLCMD.EXE -E -Q "IF (COALESCE(TRY_CONVERT(TINYINT, REPLACE('%Month%', '''', '''''')), 0) NOT BETWEEN 1 AND 12) BEGIN RAISERROR('Please enter a value 1 - 12.', 16, 1); RETURN; END; SELECT DATENAME(MONTH, '2014-%Month%-01') AS [MonthName];"
Run it without passing in any parameters. It will prompt for the month. It will then substitute that value in the query, which does its own data validation on the input.
NOTE: be sure to validate input to protect against SQL Injection. The above example replaces single-quotes with escaped-single-quotes for this reason. It also removes all single-quotes before the variable is even used in the query so the REPLACE() is just a redundant safety.
C:\>.\SingleScriptToAcceptParamForQuery.cmd
Please enter in a month: '5
Month = '5
Month with single-quotes removed = 5
MonthName
------------------------------
May
(1 rows affected)

Writing the same output to multiple logs

Is it possible to write the same output to more than one file in Batch?
My reason for wanting to do this is because I have a large batch script that produces a very detailed log. This is fine as it is, but i want to also output a trimmed back version of the log with a lot less detail in it. The Batch cannot be run multiple times either.
Say for instance I have a simple batch:
Echo This is a Batch Script >> Path\File1 & Path\File2
osql -S%SERVERNAME% -E -d%DATABASENAME% -Q%SQL% >> Path\File1
Appreciate any help.
Maybe you can use the tee command from Unix tools. Downloadable for free from here. Think of it like a "T" that a plumber might put in a pipe to send water two ways.
osql -S%SERVERNAME% -E -d%DATABASENAME% -Q%SQL% | tee file1 file2 file3
Have a look at some examples as I am not entirely sure what your full processing requirement is, see here.
If you want to do some processing on one stream you can do this:
osql -S%SERVERNAME% -E -d%DATABASENAME% -Q%SQL% | tee unfiltered.txt | FINDSTR /v "UglyStuff" > filtered.txt
Second answer, because it is different...
You could use some VBScript, like this to send your osql output to both stdout and stderr and then handle the two separately. This saves you needing to install any Unix tools.
Save this as tee.vbs
REM ############################################################################
REM File: tee.vbs
REM Author: Mark Setchell
REM I don't need any Unix purists to tell me it is not functionally idential to
REM the Unix 'tee' command, please. It does a job - that's all. And I also know
REM there is no error checking. It illustrates a technique.
REM ############################################################################
Set fso = CreateObject ("Scripting.FileSystemObject")
Set stdout = fso.GetStandardStream (1)
Set stderr = fso.GetStandardStream (2)
Do While Not WScript.StdIn.AtEndOfStream
REM Read in next line of input
Line = WScript.StdIn.ReadLine()
stdout.WriteLine(Line)
stderr.WriteLine(Line)
Loop
Then run your osql like this:
osql -S%SERVERNAME% -E -d%DATABASENAME% -Q%SQL% | cscript /nologo tee.vbs 2> unfiltered.txt | FINDSTR "goodstuff" > filtered.txt
Basically, whatever the tee.vbs script writes to stderr gets redirected to wherever 2> points, and whatever tee.vbs writes to stdout goes into the FINDSTR command.
Ideally, you could put your filtering inside the tee.vbs file for maximum flexibility.

SQLPLUS BAT File

I have a BAT file that runs a script on oracle :
sqlplus myuser/mypassword#mydatabase #C:\runthisfile.sql
I want to distribute this to other users (that don't necessarily know how to modify a BAT file).
I want the dos prompt to ask the user to enter their user and password (obviously I don't want to give them my connection details). Have tried all types of combination but all that happens is that I end up with SQL>......
Am stumped!
You can use the SET command with the /P argument in order to prompt the user for text during a batch file run, for example:
SET /P variable=Please enter text
This will then fill variable with whatever they type before hitting return.
#ECHO OFF
SET /P uname=Username:
SET /P pass=password:
This is a simple program which will prompt the first for a username, then a password.
You should then be able to pass this as an argument to sqlplus:
sqlplus %uname%/%pass%#mydatabase #C:\runthisfile.sql
Regarding with SQLPlus stop, doing nothing:
Sometimes SQLPlus finish with ... meaning that is waiting for something more.
Try to add "/" (without quotes) in the end of your SQL file to execute it.
I hope it will help...
It is the very simple code for opening SQLPLUS without entering usename and password manually.
sqlplus -L UserName/Password
For example : sqlplus -L Rak4ak#sun64/rk4
For Understanding :
sqlplus [ [] [{logon | /nolog}] [] ]
is: [-C ] [-L] [-M ""] [-NOLOGINTIME] [-R ]
[-S]
-C <version> Sets the compatibility of affected commands to the
version specified by <version>. The version has
the form "x.y[.z]". For example, -C 10.2.0
-L Attempts to log on just once, instead of
reprompting on error.
-M "<options>" Sets automatic HTML markup of output. The options
have the form:
HTML [ON|OFF] [HEAD text] [BODY text] [TABLE text]
[ENTMAP {ON|OFF}] [SPOOL {ON|OFF}] [PRE[FORMAT] {ON|OFF}]
-NOLOGINTIME Don't display Last Successful Login Time.
-R <level> Sets restricted mode to disable SQL*Plus commands
that interact with the file system. The level can
be 1, 2 or 3. The most restrictive is -R 3 which
disables all user commands interacting with the
file system.
-S Sets silent mode which suppresses the display of
the SQL*Plus banner, prompts, and echoing of
commands.
is: {[/][#] | / }
[AS {SYSDBA | SYSOPER | SYSASM | SYSBACKUP | SYSDG | SYSKM}] [EDITION=value]
Specifies the database account username, password and connect
identifier for the database connection. Without a connect
identifier, SQL*Plus connects to the default database.
The AS SYSDBA, AS SYSOPER, AS SYSASM, AS SYSBACKUP, AS SYSDG,
and AS SYSKM options are database administration privileges.

Resources