Change delimiter in a DB2 script - sql

I have setup DB2 v11.5.5.1 in a Docker container and accessed it via DBeaver.
I want to run a script with a CREATE PROCEDURE statement on DB2 database.
But it returns SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "E IF EXISTS TEMP_IDS".
The sample script I tried is here.
--#SET DELIMITER $$
CREATE PROCEDURE proc_name ()
BEGIN
-- some statements;
END$$
How can I solve this delimiter issue in DB2 script? I think the issue with changing the delimiter.

Your mistake is that you are trying to use a Db2 CLP (command line processor) feature inside DBEaver, i.e you are trying to use --#SET TERMINATOR....
This feature --#SET TERMINATOR is available if you execute your script with the Db2 clp (i.e. on MS-Windows that is db2.exe, and on linux/unix the db2 command in the shell).
For Dbeaver, a jdbc application, there is a different method to configure the alternative statement terminator / delimiter. Use the properties settings to find this option and choose a valid character in that GUI. Then retry.
For example, in Dbeaver Community Edition version 2021.04, use:
File > Properties > Editors > SQL Exitor > SQL Processing: "Statements Delimiter"

Related

DB2 Stored Procedure IF/ELSE -- What am I missing?

Trying to modify a stored procedure at work and looking to add some conditional logic into the procedure. I created a small test procedure just to try and understand IF/ELSE logic and I keep getting barked at by DBeaver (my SQL UI). I took the example pretty much directly off an IBM documentation web site. Can someone tell me what I'm missing here:
CREATE PROCEDURE IFTEST(IN rating INTEGER, OUT res VARCHAR(1))
LANGUAGE SQL
BEGIN
IF rating = 1 THEN
SET res = '2';
-- ELSE IF rating = 2 THEN
-- SET res = 3;
ELSE
SET res = '4';
END IF;
END
It keeps giving me this:
SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found following "s = '4'". Expected tokens may include: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.26.14
This is a frequently asked question.
First ensure your code is syntactically valid: in your case verify that each conditional statement has its own END IF, or alternatively use ELSEIF (and not ELSE IF) when you want to have a single conditional statement.
Next, verify your compound statement delimiters.
When you have a 'block' (multiple SQL statements) that executes as a single-statement (also known as compound SQL compiled), the Db2 client tool needs to recognize the end of the block.
The SQL standard does not specify how to do this, so different RDBMS tools use different techniques.
Many people who use Db2 will use the # character as the compound SQL block delimiter instead of the default character which is semi-colon. That semi-colon is still required to delimit the statements inside of the block, but the block also needs to have some delimiter, so if you use # then the final character in your stored-procedure should be that # character. You then select the block including this delimiter and ask DBeaver to execute it as a single compound statement.
DBeaver lets you do this configuration via its settings GUI.
Example navigation in DBeaver (depending on your version of DBeaver):
Properties > Editors > SQL Editor > SQL Processing
Statements delimiter: #
Ignore native delimiter (tick)
Blank line is statement delimiter (only use this if you code accordingly)
Remove trailing query delimiter (tick)
When you make these changes, you make need to disconnect the data source, and reconnect before they will be effective.
You can also make these changes in 'Global Settings' if you only use Db2 data sources and want these settings for all databases.
But again, you may need to disconnect and reconnect before the settings become effective.

Install4j: SQL Script and statement delimiter

I try to run several SQL-Statements in an SQL Script action for an Oracle dbms inside an installer and as part of a JDBC container action.
The script is encoded as UTF-8, and contains several statements, delimited by ";" and a new line between each statement, like this
statement 1;
statement 2;
...
The statements contain installer variables that are replaced before execution. I used the semicolon as a statement separator in the SQL script action.
The first statement throws an error
Error executing script line "CREATE user testconuser identified by xxx TEMPORARY TABLESPACE temp;",
error message: "ORA-00911: invalid character"
The statement itselfs works fine within SQLPLUS, but the problems seems to be the semicolon, that is still part of the statement executed by install4j.
In a JDBC sql statement, semicolons are not valid.
I also tried to remove the semicolons from the statements and used "\n" as statement delimiter, but then the sql script actions fires all sql statements within the script at once, so it looks like the "\n" is not recognized.
I am using install4j 6.1.5 build 6349. The platform is windows and the sql script is build on windows.
Any idea what I should change?
Any help would be highly appreciated, thanks a lot in advance,
Alex
I used the semicolon as a statement separator in the SQL script action. The first statement throws an error Error executing script line
and
I also tried to remove the semicolons from the statements and used "\n" as statement delimiter
Both are bugs in 6.1.5 and will be fixed in 6.1.6. Please contact support#ej-technologies.com to get a build where you can verify that this will work for you.

Run create function code without SQLCMD

I have DDL code to create a function that runs flawlessly from sqlcmd and other specific SQL Server clients:
/*
* Émulo de la función LPAD() de Oracle
*/
CREATE FUNCTION LPAD
(
#cadena VARCHAR(MAX), -- Texto de partida
#tamano INT, -- Tamaño de la cadena resultante
#relleno CHAR -- Carácter de relleno
)
RETURNS VARCHAR(MAX)
AS
BEGIN
return REPLICATE(#relleno, #tamano - LEN(#cadena)) + #cadena;
END
GO
However, it won't typically run from cross-DBMS clients (SQL Fiddle, DBeaver, HeidiSQL...):
[102] Incorrect syntax near '#cadena'.
I suspect it's got to do with the GO batch separator not being implemented. If that's the case, is there an alternative syntax?
To sum up my comments:
The standard delimiter in SQL is the ;.
However, when running a code block that contains embedded semicolons (e.g. when creating a stored procedure) the standard delimiter cannot be applied as in that case the block wouldn't be sent as a single statement.
For those cases the SQL client usually has some way of defining an alternate delimiter that marks the end of a block and usually has a higher precedence than the ;
Microsoft calls this "alternate delimiter" the "batch separated" and decided to use GO for this and all Microsoft tools stick to that. In SSMS this batch separator can actually be configured to something else.
Oracle's SQL*Plus (and SQL Developer) use / for this.
Other SQL clients allow a dynamic definition inside a SQL script typically using delimiter (or something similar) to change the delimiter for subsequent statements.
As I have never used DBeaver or HeidiSQL I cannot tell how this is done in those SQL clients.

DB2 - How to run an ad hoc select query with a parameter in IBM System i Access for Windows GUI Tool

I would like to run some ad hoc select statements in the IBM System I Navigator tool for DB2 using a variable that I declare.
For example, in the SQL Server world I would easily do this in the SQL Server Management Studio query window like so:
DECLARE #VariableName varchar(50);
SET #VariableName = 'blah blah';
select * from TableName where Column = #VariableName;
How can I do something similar in the IBM System I Navigator tool?
I ran across this post while searching for the same question. My coworker provided the answer. It is indeed possible to declare variables in an ad hoc SQL statement in Navigator. This is how it is done:
CREATE OR REPLACE VARIABLE variableName VARCHAR(50);
SET variableName = 'blah';
SELECT * FROM table WHERE column = variableName;
DROP VARIABLE variableName;
If you don't drop the variable name it will hang around until who knows when...
At the moment, we're working on the same issue at work. Unfortunaly, we concluded that this is not possible. I agree, it would be great but it just doesn't work that way. iNavigator doesn't support SET or Define. You can do that in embedded SQL but this is not embedded SQL. Even if you create a separate document (xxx.sql), then need to open this document to run the script what makes it an interactive script (that is, DECLARE SECTION is not allowed).
As an alternative, in the SQL screen/script you can use CL:. Anything after this prefix is executed as CL command. You may manipulate your tables (e.g. RNMF) this way.
As a second alternative, the iSeries does support Rexx scripts (default installed with the os). Rexx is good dynamic script language and it does support embedded SQL. I've done that a lot of times and it works great. I even created scripts for our production environment.
Just create one 'default' script with an example PREPARE and CURSOR statement and copy at will. With that script you can play around. See the Rexx manual for the correct syntax of exec-sql. Also, you do have STDIN and STDOUT but you can use 'OVRDBF' to point to a database table (physical file). Just let me know if you need an example Rexx script.
Notice that the manual "SQL embedded programming" does have Rexx examples.
Here are a couple of other alternatives.
Data Transfer Tool - You can run the iSeries Data Transfer Tool from the command line (RTOPCB). First, run the GUI version and create a definition file. If you edit this file with a text editor, you will see that this is just an old-fashioned INI file and you can easily find the line with the query in it. From there, you could write a batch file or otherwise pre-process the text file to allow you to manipulate the query before submitting it to the query tool.
QSHELL - If you can log on to the iSeries interactively, then you may find the QSHELL environment more familiar than CL or REXX (although REXX is kind of fun). QSHELL is a full POSIX environment running on the iSeries. Use the command STRQSH to start QSHELL. You can have ksh or csh as a shell. Inside QSHELL, there is a command called "db2" that submits queries. So, you should be able to do something like this inside QSHELL:
system> VariableName = 'blah blah'
system> db2 "select * from TableName where Column = \'$VariableName\'"
You may have to fiddle with the quotes to get ksh to pass them correctly.
Also, inside QSHELL, you should have a full Perl installation that will allow you to use DBI to get data.
Some other ways to interact with data on the iSeries: query from the client with Python via ODBC; query from the client with Jython via JDBC; install Jython directly on the iSeries and then query via JDBC.

db2 sql script file

I have an oracle script that I am trying to convert to valid db2 syntax. Within this sql file I have various calls to other sql files passing in a parameter using the '#' syntax.
e.g.
#script1 param1
#script2 param2
Can anyone help me with valid db2 equivalent statements? Is there an equivalent run command in db2? is it possible to pass parameters to a sql script in db2?
thanks,
smauel
The thing you are after is the DB2 Command Line Processor (CLP).
If you want to execute a script, you would execute in the CLP:
db2 -vtf script1
-f tells the CLP to run command input from the given file.
Here's the full list of options.
Unfortunately db2 doesn't support passing parameters to a script. You would have to combine your db2 -vtf commands with other scripting commands (such as sed) to generate the scripts for you, as in this example.
1) place the filename.sql file in SQLLIB/BIN
2) run db2cmd
3) execute this to connect to the required db
db2 connect to *dbname* user *userid* using *password*
4) excute this command
db2 -vtf *filename.sql*
This should execute the sql statements in the file one by one. The sql statements must be ending with a semicolon
There is an easier way for passing in parameters, that works fine for us (it might not work with (complex) multiline sql statements).
Convert your sql-script into a shell script by adding 'db2 ' at the beginning of each line. Than you can use the standard variable replacement syntax from your shell in your scripts.
so instead of
insert ...
update ...
you will have
db2 insert ...
db2 update ...
Place file in one directory.
Open db2cmd.exe as administrator
Navigate to directory where you have place the script
type db2 -vtf `