Stored procedure can not be parsed during migration - hsqldb

I'm using the api of flyway 1.7 for migrating a hsql database.
I have some problems with stored procedures. The following script works fine
with hsql database manager:
CREATE TABLE CUSTOMER (
firstname VARCHAR(50),
lastname VARCHAR(50),
mod_ts TIMESTAMP
);
CREATE PROCEDURE new_customer(firstname VARCHAR(50), lastname VARCHAR(50), address VARCHAR(100))
MODIFIES SQL DATA
BEGIN ATOMIC
INSERT INTO CUSTOMER VALUES (firstname, lastname, CURRENT_TIMESTAMP);
END
But I think during a flyway migration the script is not parsed correctly (it looks like
flyway believes the second statement ends after the semicolon).
Here is the corresponding log output:
DEBUG 2012-11-22 14:16:00,232 [main] (SqlScript.java:161) - Found statement at line 1: create table CUSTOMER (
firstname varchar(50),
lastname varchar(50),
mod_ts timestamp
);
DEBUG 2012-11-22 14:16:00,232 [main] (SqlScript.java:161) - Found statement at line 7: CREATE PROCEDURE new_customer(firstname VARCHAR(50), lastname VARCHAR(50), address VARCHAR(100))
MODIFIES SQL DATA
BEGIN ATOMIC
INSERT INTO CUSTOMER VALUES (firstname, lastname, CURRENT_TIMESTAMP);
DEBUG 2012-11-22 14:16:00,232 [main] (SqlStatement.java:75) - Executing SQL: create table CUSTOMER (
firstname varchar(50),
lastname varchar(50),
mod_ts timestamp
)
DEBUG 2012-11-22 14:16:00,232 [main] (SqlStatement.java:75) - Executing SQL: CREATE PROCEDURE new_customer(firstname VARCHAR(50), lastname VARCHAR(50), address VARCHAR(100))
MODIFIES SQL DATA
BEGIN ATOMIC
INSERT INTO CUSTOMER VALUES (firstname, lastname, CURRENT_TIMESTAMP)
ERROR 2012-11-22 14:16:00,232 [main] (DbMigrator.java:231) - com.googlecode.flyway.core.exception.FlywayException: Error executing statement at line 7: CREATE PROCEDURE new_customer(firstname VARCHAR(50), lastname VARCHAR(50), address VARCHAR(100))
MODIFIES SQL DATA
BEGIN ATOMIC
INSERT INTO CUSTOMER VALUES (firstname, lastname, CURRENT_TIMESTAMP)
ERROR 2012-11-22 14:16:00,232 [main] (DbMigrator.java:236) - Caused by org.hsqldb.HsqlException: unexpected end of statement: required: ; : line: 4
Is there a way to solve this problem?
EDIT I just made an interesting observation. If I use the flyway command-line program,
then it works perfectly.

Upgrade to Flyway 2.0. It added support for BEGIN ATOMIC blocks in Hsql.

Related

T-SQL Insert into truncates data on insert

This is odd. I have two separate store procedures inserting into one table.
One works fine while the other truncates all but the 1st character on four varchar(50) columns. I've tested this by executing the SP in SQL.
Only difference is the working query is moving data from one table to the other. The non-working stored procedure is receiving parameters. In the non working query, there are int columns and they work fine. It's just the four varchar.
This works fine.
INSERT INTO PurchaseOrderItems_tbl (POID, VendorAccountID, POTicketID, POInvItemID, POLineItemQty, PartManufPartNum, PartOrderDesc, PartOrderManufacture, PartOrderModel, POType, PODescription, POStatusID, PartRequestedBy, POGLCode)
SELECT
POID, VendorAccountID, PartOrderTicketID, PartInvID,
POItemQty, PartManufPartNum, PartOrderDesc,
PartOrderManufacture, PartOrderModel, POType,
PODescription, POStatusID, PartRequestedBy, POGLCode
FROM
PurchaseOrderTmp_tbl
This is the non working stored procedure:
Procedure [dba].[xxxxx]
(
#POID int,
#VendorAccountID int,
#PartOrderTicketID int,
#PartInvID int,
#PartManufPartNum varchar,
#PartOrderDesc varchar,
#PartOrderManufacture varchar,
#PartOrderModel varchar,
#PartOrderType varchar,
#PartOrderQTY int
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO PurchaseOrderItems_tbl
([POID],[VendorAccountID],[POInvItemID],[POTicketID],[PartManufPartNum],[PartOrderDesc],[PartOrderManufacture],[PartOrderModel],[POLineItemQty])
VALUES (#POID, #VendorAccountID, #PartInvID, #PartOrderTicketID, #PartManufPartNum, #PartOrderDesc, #PartOrderManufacture, #PartOrderModel, #PartOrderQTY)
END
I am completely baffled as I see nothing wrong and the qry does not error.
Thanks in advance folks
Your stored proc does not specify the length of the varchar inputs - by default this length is 1.
procedure [dba].[xxxxx]
(
#POID int,
#VendorAccountID int,
#PartOrderTicketID int,
#PartInvID int,
#PartManufPartNum varchar(50), -- match the column length
...etc

Db2 stored procedure to insert

I'm new to db2 and stored procedure i created a stored procedure to insert records into a database but the stored procedure doesn't work, the code is as follows:
drop procedure product_create ;
CREATE PROCEDURE product_Create(
out errmsg char(256),
in inCucode char(6),
in inProdCode char(25),
in inDescription char(80),
in inUPC char(25),
in inuom char(3),
in instdpack decimal(5,0),
in inweight decimal(9,4),
in inlength decimal(9,4),
in inwidth decimal(9,4),
in inheight decimal(9,4)
)
language sql
BEGIN
if errmsg = ' '
insert INTO prmast
( prcucd,
prprcd,
prdes1,
prupc#,
prworu,
prwuts,
prntwt,
prlong,
prwide,
prhigh
)
values ( inCucode,
inProdCode,
inDescription,
inUPC,
inuom,
instdpack,
inweight,
inlength,
inwidth,
inheight,
) ;
end if ;
return ;
end
Is this the correct structure for an insert query in stored procedure am i forgetting anything, your help will be appreciated.
I reproduced your issue as following:
Create a table "prmast":
CREATE TABLE prmast(prcucd char(6), prprcd char(25), prdes1 char(80), prupc# char(25), prworu char(3), prwuts dec(5,0), prntwt dec(9,4), prlong dec(9,4), prwide dec(9,4), prhigh dec(9,4));
Write the stored procedure and save it to a file called sol.txt
CREATE OR REPLACE PROCEDURE product_Create(
out errmsg char(5),
in inCucode char(6),
in inProdCode char(25),
in inDescription char(80),
in inUPC char(25),
in inuom char(3),
in instdpack decimal(5,0),
in inweight decimal(9,4),
in inlength decimal(9,4),
in inwidth decimal(9,4),
in inheight decimal(9,4)
)
language sql
BEGIN
DECLARE SQLSTATE CHAR(5);
Insert INTO prmast
( prcucd,
prprcd,
prdes1,
prupc#,
prworu,
prwuts,
prntwt,
prlong,
prwide,
prhigh
)values
( inCucode,
inProdCode,
inDescription,
inUPC,
inuom,
instdpack,
inweight,
inlength,
inwidth,
inheight
) ;
SET errmsg = SQLSTATE;
end#
run the procedure: db2 -td# -vf sol.txt
Then, I call the procedure:
db2 "call product_Create(?, 'a','b','c','d','e',6,7,8,9,10)"
Value of output parameters
Parameter Name : ERRMSG
Parameter Value : 00000
Return Status = 0`
Verify it works:
`db2 select * from prmast
PRCUCD PRPRCD PRDES1 PRUPC# PRWORU PRWUTS PRNTWT PRLONG PRWIDE PRHIGH
------ ------------------------- -------------------------------------------------------------------------------- ------------------------- ------ ------- ----------- ----------- ----------- ---------
a b c d e 6. 7.0000 8.0000 9.0000 10.00
00
1 record(s) selected.`
There are several points to be noticed for your procedure:
You can use CREATE OR REPLACE PROCEDURE to define your procedure. It will drop existing procedure definition and replace it with the definition you just run. In other words, you don't have to explicitly DROP PROCEDURE
char(255) is out of range. declare output "errmsg" as char(5) should be good enough.
You can use SET statement to explicitly check if your SQL statement executed successfully or not.
The # symbol at the end of procedure indicates db2 that to not use ; as end of statement because you use ; as end of statement of a SQL, which belongs to part of stored procedure definition. That is also why you want to use -td# option when you execute your clp. That tells DB2 to use # instead of ; as end-of-statement symbol.
Also, there is , right after column "inheight", which is the last column and should not have , following
When calling stored procedure, ? is required as placeholder for "OUT" parameter.
One more note, if you want to insert values from the selection result of another table, you may want to use "cursor" instead of explicitly supplying the values to your stored procedure.

HSQLDB Stored Procedure Error: attempt to assign to non-updatable column

I am using HSQLDB 2.3.2 and am getting a bizarre error when trying to create a stored procedure.
My addresses table:
CREATE TABLE IF NOT EXISTS addresses (
address_id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1) NOT NULL PRIMARY KEY,
address_line_1 NVARCHAR(500) NOT NULL,
address_line_2 NVARCHAR(500),
address_city NVARCHAR(100) NOT NULL,
address_postal_code NVARCHAR(25) NOT NULL,
CONSTRAINT uc_addresses UNIQUE (address_line_1, address_city)
)
An insert to populate it:
INSERT INTO addresses (
address_line_1,
address_city,
address_postal_code
) VALUES (
'123 Test Blvd.', 'Testville', '11111'
)
And my proc:
CREATE PROCEDURE sp_get_address_by_id(
IN address_id INTEGER,
OUT address_id INTEGER,
OUT address_line_1 NVARCHAR(500),
OUT address_line_2 NVARCHAR(500),
OUT address_city NVARCHAR(100),
OUT address_postal_code NVARCHAR(25))
READS SQL DATA
BEGIN ATOMIC
SELECT
a.address_id,
a.address_line_1,
a.address_line_2,
a.address_city,
a.address_postal_code
INTO
address_id,
address_line_1,
address_line_2,
address_city,
address_postal_code
FROM
addresses a
WHERE
a.address_id = address_id;
END
When I run this I get:
Error: attempt to assign to non-updatable column
SQLState: 0U000
ErrorCode: -2500
Questions:
What is wrong with my proc (what is producing this error)?
I'm actually looking for a CREATE IF NOT EXISTS-type declaration, so I can run this script over and over again and the procedure will only get created one time if it doesn't already exist. Will this happen or do I need to change the syntax to accomplish IF NOT EXISTS?
Try the syntax below, according to the hsqldb documentation
http://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_psm_assignment
The SET statement is used for assignment. It can be used flexibly with
rows or single values.
Also change the address_id parameter to type INOUT and remove the duplicate address_id parameter lines.
CREATE PROCEDURE sp_get_address_by_id(
INOUT address_id INTEGER,
OUT address_line_1 NVARCHAR(500),
OUT address_line_2 NVARCHAR(500),
OUT address_city NVARCHAR(100),
OUT address_postal_code NVARCHAR(25))
READS SQL DATA
BEGIN ATOMIC
SET (address_id,
address_line_1,
address_line_2,
address_city,
address_postal_code)
=
(
SELECT
a.address_id,
a.address_line_1,
a.address_line_2,
a.address_city,
a.address_postal_code
FROM
addresses a
WHERE
a.address_id = address_id
);
END
You can try adding this as the first statement in your script if you want to drop the procedure if it already exists, so that you can re-run the script many times. You can search the documentation for <specific routine designator> for more info.
DROP SPECIFIC PROCEDURE sp_get_address_by_id IF EXISTS;
In your procedure you have two parameters with the same name:
IN address_id INTEGER,
OUT address_id INTEGER,
It may cause a problem when you refer to address_id in the body of procedure.
You should rather use:
INOUT address_id INTEGER,
instead of these two lines.
Answering your second question:
Why do you want to run this script over and over again without rebuilding the procedure? Running this script again has sense when something has changed in it.
If you don't plan to change this procedure but you want to change other things in your script then maybe you should simply move this procedure to other script and run it only once
If you plan to change the body of procedure then it should be rebuilded every time. So you should use CREATE OR REPLACE PROCEDURE
For followers, the same error message is thrown if you do this:
PreparedStatement selectStmt = conn.prepareStatement(query);
ResultSet rs = selectStmt.executeQuery()) {
rs.next();
rs.updateLong("column", value); // boom
one fix is to use this style:
PreparedStatement selectStmt =
conn.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

Error with output clause in insert statement

I'm a little stumped as to why my output clause won't work. Am I doing something silly? I keep getting the error, " Incorrect syntax near 'output'."
--Create the table to insert into, with identity
create table #testtab(
businessno int identity(1,1),
businessname varchar(100),
businessref varchar(50),
moduser varchar(10),
moddate datetime,
modtype char(1)
);
--Insert statement with output to capture inserted id numbers
insert into #testtab (businessname, businessref, moduser, moddate, modtype)
output inserted.businessno,inserted.businessref
values('asd','asd','asd',getdate(),'x');
This is in 2008R2.
Thanks,
Dan
Ah.... my bad. I was actually connected to a SQL 2000 instance from SSMS. Woops. Doesn't look like 2000 supports output. Sigh

How to create Temporary table with Dynamic query in SQL Server 2005

I want to create Temporary table dynamically in SQL Server 2005 like below.
Create Table ##EmpMonthlyTimeReport
(
EmpID UNIQUEIDENTIFIER,
EmpName VARCHAR(100),
TaskId UNIQUEIDENTIFIER,
[07 Nov] NVARCHAR(10),
[08 Nov] NVARCHAR(10),
[09 Nov] NVARCHAR(10)
)
In the above ##EmpMonthlyTimeReport table, columns [07 Nov], [08 Nov], [09 Nov] are NOT static. They are creating dynamically through another function.
Hence, I am dynamically constructing the above table in one variable called #EmpMonthlyTimeReport and I'm executing the constructed sql string like below:
EXEC(#EmpMonthlyTimeReport)
I am getting the following error:
Msg 50000, Level 16, State 1, Procedure SVS_WorkOnWeekends, Line 157
The name 'INSERT INTO ##EmpMonthlyTimeReport(EmpID, EmpName, TaskId)
SELECT EmpId, EmpName, TaskId FROM TableData
SELECT * FROM ##EmpMonthlyTimeReport
DROP TABLE ##EmpMonthlyTimeReport' is not a valid identifier.
Very silly work around.
I have changed the #EmpMonthlyTimeReport variable declaration from VARCHAR(MAX) to NVARCHAR(MAX)
That's it. Everything is working as expected.