I'd like to translate this very simple stored procedure from the Sybase SQL dialect to the HSQLDB dialect:
CREATE PROCEDURE dbo.some_proc
AS
BEGIN
SELECT int_param1 FROM control WHERE id_param = "SOME_PARAM" AND id_active = "Y"
END
In my humble opinion the documentation for HSQLDB is very mysterious about stored procedures. I couldn't find the right way to do it. I'm using HSQLDB version 2.3.1.
This can be expressed as a FUNCTION in HSQLDB
CREATE FUNCTION some_proc () RETURNS TABLE(VAL INT)
READS SQL DATA
BEGIN ATOMIC
RETURN TABLE(SELECT int_param1 FROM control WHERE id_param = 'SOME_PARAM' AND id_active = 'Y');
END
The function returns a single row table with all the values.
If your procedure always returns a single value, the declaration can be different to reflect this:
CREATE FUNCTION some_proc2 () RETURNS INT
READS SQL DATA
BEGIN ATOMIC
RETURN (SELECT int_param1 FROM control WHERE id_param = 'SOME_PARAM' AND id_active = 'Y');
END
Related
I am working with SQL manager lite for Interbase/Firebird application. I have downloaded firebird database, successfully connected to that database and its host, but now I want to create procedure.
I couldn't done it via tutorials, so I decided to just click New->Procedure and do that automatically. But doing this way I still have errors.
My code what I have tried without clicking New->Procedure:
CREATE PROCEDURE MyProc
AS
SELECT M_DOKUMENTY.NDZIEN FROM M_DOKUMENTY WHERE M_DOKUMENTY.SRODZAJ = '1234'
GO;
The code which was generated using New->Procedure wizard:
CREATE PROCEDURE SHOW_ALL
AS
BEGIN
/* Procedure body */
SELECT
M_DOKUMENTY.NDZIEN,
M_DOKUMENTY.CKIERUNEK,
M_DOKUMENTY.CMEDIUM FROM M_DOKUMENTY WHERE M_DOKUMENTY.SRODZAJ = '1234'
SUSPEND;
END;
But when I am clicking that lightning icon (compile) it complains about error:
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 9, column 3.
SUSPEND.
How to fix that?
Screenshot of error in SQL Manager lite
The problem is that your syntax is wrong. You need to define the output parameters, and you need to use either select ... into <list of variables> to select a single row, or for select ... into <list of variables> do to loop over multiple rows.
Your stored procedure should be something like:
CREATE PROCEDURE SHOW_ALL
RETURNS (NDZIEN varchar(50), CKIERUNEK varchar(50), CMEDIUM varchar(50))
AS
BEGIN
/* Procedure body */
for SELECT
M_DOKUMENTY.NDZIEN,
M_DOKUMENTY.CKIERUNEK,
M_DOKUMENTY.CMEDIUM
FROM M_DOKUMENTY
WHERE M_DOKUMENTY.SRODZAJ = '1234'
into :NDZIEN, :CKIERUNEK, :CMEDIUM
do
SUSPEND;
END
If your select only produces a single row, then you could also consider using
CREATE PROCEDURE SHOW_ALL
RETURNS (NDZIEN varchar(50), CKIERUNEK varchar(50), CMEDIUM varchar(50))
AS
BEGIN
/* Procedure body */
SELECT
M_DOKUMENTY.NDZIEN,
M_DOKUMENTY.CKIERUNEK,
M_DOKUMENTY.CMEDIUM
FROM M_DOKUMENTY
WHERE M_DOKUMENTY.SRODZAJ = '1234'
into :NDZIEN, :CKIERUNEK, :CMEDIUM;
SUSPEND;
END
Notice the ; after the into clause. In this case you could also leave out the SUSPEND;. That will make the stored procedure executable instead of selectable. Depending on how you want to use it, that could be a better choice.
See the Firebird documentation on created stored procedures and its procedural SQL language for more information.
G'day. I'm trying to create a basic function which checks for the number of records matching a certain criteria. If there are none then it performs an insert and returns returns 0, otherwise it updates the existing record and returns 1. I'm getting a syntax error at the location of the Insert and Update statements. Here is my SQL script (FYI I'm new to pervasive and if anyone has a better way to perform an update/insert then I'm all ears/eyes):
CREATE FUNCTION "InsertUpdateWebData"(:KeyType CHAR(1), :KeyValue CHAR(50),
:WebData CHAR(100), :WhiteSpace LONGVARCHAR, :Spare CHAR(97)) RETURNS INTEGER
AS
BEGIN
DECLARE :RecordCount INTEGER;
SET :RecordCount = (SELECT COUNT(*) FROM SYS_WebData WHERE WBD_KeyType
= :KeyType and WBD_KeyValue = :KeyValue);
IF :RecordCount = 0 THEN
BEGIN
INSERT INTO SYS_WebData(WBD_KeyType, WBD_KeyValue, WBD_Data,
WBD_WhiteSpace, WBD_Spare) VALUES (:KeyType, :KeyValue, :WebData,
:WhiteSpace, :Spare);
RETURN 0;
END
ELSE
BEGIN
UPDATE SYS_WebData SET WBD_Data = :WebData, WBD_WhiteSpace = :WhiteSpace,
WBD_Spare = :Spare WHERE WBD_KeyType = :KeyType AND WBD_KeyValue =
:KeyValue;
RETURN 1;
END
END IF
END
What would be the correct syntax to do this?
From the Pervasive documentation:
Restrictions
You cannot use the CREATE DATABASE or the DROP DATABASE statement in a
user-defined function. The table actions CREATE, ALTER, UPDATE,
DELETE, and INSERT are not permitted within a user-defined function.
You should be able to change it from CREATE FUNCTION to CREATE PROCEDURE and have it work. I did that and it created the procedure.
I'm working passing ms sql server statements into hana sql statements. I have a variable (Tab) type Table and a variable string (query) defined as:
Hana Statement
CREATE TYPE "tab_table_TYPE" AS TABLE ("DocEntry" integer, "LineId" integer, "VisOrder" integer, "Object" nvarchar(20));
v_Tab tab_table_TYPE
query := 'SELECT [DocEntry],[LineId],[VisOrder] ,[Object] FROM [#INV_AFC]';
so I'm trying to convert this Ms Sql Statement into a Hana Statement :
Ms Sql Server Statement
INSERT INTO #v_Tab([DocEntry],[LineId],[VisOrder],[Object]) exec (#query)
I wish to use an internal table type variable which can hold the resultset from the query!
When I use the Sql Converter with this sentence displays this error:
--[Note:ErrorModifier] INSERT INTO statement does not support EXEC; use EXEC('insert into table '+ originalstatement)
--[Note:Stringifier] SAP HANA does not support InsertTarget
Finally the question is : How would be the correct Hana Sql Statement for this case?
The syntax of your table-type creation is correct. I guess you are trying to execute the query inside a procedure.
Inside a procedure, you have different options. If your query is only a partial result and you want to run further statements on the result set of the query, you don't need to initialize a table variable at all. Just assign a variable to a resultset:
table_variable = SELECT DocEntry, LineId, VisOrder, Object FROM INV_AFC;
// Use table_variable for further statements, for example:
SELECT count(*) INTO resultSetCount FROM :table_variable;
If your query is already the final result, you can easily define an output variable and directly assign your result set as output variable. For example:
CREATE PROCEDURE "YOURSCHEMA"."SomeProcedureName" (
in someInputVariable1 NVARCHAR(255),
in someInputVariable2 BIGINT,
out tableVariable "YOURSCHEMA".tab_table_TYPE)
LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER AS
BEGIN
tableVariable = SELECT DocEntry, LineId, VisOrder, Object FROM INV_AFC;
END;
When you then call this procedure the 3rd parameter will automatically contain your result set:
call "YOURSCHEMA"."SomeProcedureName"('someString', 123, ?);
I have a large stored procedure that returns a record for a person, there are four fields that I need to return very specific values for. I have another stored procedure that performs this specific action.
The small stored procedure is as follows:
SELECT TOP 1
wea.field,
wea.degree,
wea.degreeyear,
wpp.ProgramCategory
FROM dbo.webeventaffiliation wea
LEFT JOIN dbo.WebProgramParticipants wpp
ON
wea.userid = wpp.UserID AND
wea.eventid = wpp.eventid
INNER JOIN dbo.WebProgramCategoryDescriptions wpcd
ON
wpcd.ProgramCategory = wpp.ProgramCategory
WHERE wea.UserID = #UserID
ORDER BY wea.datelastmodified DESC
LARGE STORED PROCEDURE SAMPLE RETURN DATA:
Name: XXXXX
Address: XXXXX
Field: [small stored procedure value]
Degree: [small stored procedure value]
DegreeYear: [small stored procedure value]
ProgramCategory: [small stored procedure value]
My question is how do I get the 4 data items from this stored procedure into their respective columns within the dataset that is returned from the large stored procedure?
Using a table-valued function instead of a stored procedure could be helpful. You will be able to use the TVF just like a table ie:
SELECT
COLUMNS_NAMES
FROM
TVF(PARAMS)
As your small stored procedure doesn't write anything, you could just write it as a table valued function.
You can then apply the function to an entire data-set by using APPLY.
(Table valued functions that are written INLINE (not multi-statement) are then explanded macro-like to execute extremely efficiently. This is perfect for your description as the function would just be a single SELECT statement already.)
The Function:
CREATE FUNCTION dbo.your_function(#user_id AS INT)
RETURNS TABLE
AS
RETURN
<your query>
The function used in a query inside your big SP:
SELECT
...,
user_detail.field,
user_detail.degree,
user_detail.degreeyear,
user_detail.programcategory
FROM
...
CROSS APPLY
dbo.your_function(some_table.user_id) AS user_detail
In general I use functions to encapsulate queries, and only wrap them up in Stored Procedures if...
1) I need to write data. (Functions can't INSERT, UPDATE or DELETE)
2) I want to create an API like interface to client applications.
Since you're getting only one row with four values you could use OUTPUT parameters:
EXECUTE SomeSmallerProcedure
#field OUTPUT, #degree OUTPUT, #degreeyear OUTPUT, #ProgramCategory OUTPUT;
Your procedure listed above would change to:
ALTER PROCEDURE SomeSmallerProcedure
#field varchar(255) OUTPUT,
#degree varchar(255) OUTPUT,
#degreeyear varchar(255) OUTPUT,
#ProgramCategory varchar(255) OUTPUT
AS BEGIN SET NOCOUNT ON;
SELECT TOP 1
#field = wea.field,
#degree = wea.degree,
#degreeyear = wea.degreeyear,
#ProgramCategory = wpp.ProgramCategory
-- ... rest as before
The signature of your procedure above would have to include those parameters explicitly for OUTPUT.
I'm trying to use a simple function in SQL server 2005 and it generates an error.
CREATE FUNCTION [dbo].[fn_data_stat_cc_update]
(
#result char
)
RETURNS char(1)
AS
BEGIN
truncate table stg_data_cancer_center;
INSERT INTO stg_data_cancer_center(
mrn, pt_city, pt_state, pt_zip, pt_pri_dx, clinic, source
SELECT rtrim(ltrim(mrn)) as mrn,
pat_city, pat_state, zipcode, exact_icd9_code_pri_dx, 'clinic' =
case
when inst_id = 1 then 'CANRAD'
when inst_id = 2 then 'CANHAM'
else #result--''
end, 'MOSAIQ' as Source
from stg_mosaiq_patient;
RETURN LTRIM(RTRIM(#result))
END
Errors are:
Procedure fn_data_stat_cc_update, Line 18
Invalid use of side-effecting or time-dependent operator in 'TRUNCATE TABLE' within a function.
Procedure fn_data_stat_cc_update, Line 25
Invalid use of side-effecting or time-dependent operator in 'INSERT' within a function.
You can't.
You need to use a stored procedure. Functions are not allowed to have side effects such as modifying data.