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:
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
?When an error is encountered within a stored procedure, the best you can do (assuming it’s a non-fatal error) is halt the sequential processing of the code and either branch to another code segment in the procedure or return processing to the calling application. Notice that the previous sentence is specific to non-fatal errors.
HSQLDB supports core SQL updatability features, plus some enhancements from the SQL optional features. A query expression is updatable if it is a SELECT from a single underlying base table (or updatable view) either directly or indirectly. A SELECT statement featuring DISTINCT or GROUP BY or FETCH, LIMIT, OFFSET is not updatable.
When a non-fatal error occurs within a procedure, processing continues on the line of code that follows the one that caused the error. The following example demonstrates how a fatal error affects a procedure. USE tempdb go CREATE PROCEDURE ps_FatalError_SELECT AS SELECT * FROM NonExistentTable PRINT 'Fatal Error' go EXEC ps_FatalError _SELECT
If the execution of the <SQL procedure statement> specified in the handler declaration throws an exception itself, then it is handled by the handlers that are currently active at an enclosing (outer) BEGIN ... END block. The <SQL procedure statement> can itself be a compound statement with its own handlers.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With