Is it possible to load a table from a with statement via a stored procedure in HANA? Nothing i try seems to work, and the only thing that does work when creating a procedure is just displaying the data from the with statement via a select. Below I show three examples I have tried for accessing with statement data. Currently on HANA revision 84. Please note the table create is just for purposes of the test example.
CREATE PROCEDURE test_proc
LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER
AS
BEGIN
create table t1 (cal_day date);
with w1 as (
select current_date cal_day from dummy
)
--works just fine but isn't loading the data into anything
select * from w1;
--get indentifier must be declared error
select cal_day into t1 from w1;
--get incorrect syntax error
insert into t1
select cay_day from w1;
END
When you want to execute DDL statements in a SQLScript procedure you'll need to use dynamic SQL for that (EXEC).
Related
Being a recent convert from SQL Server, I am getting to know Postgresql a bit.
I really hate having to write nested selevt statements in SQL since I find that the readability and maintainability of the code suffers when I do.
Usually I would create a stored procedure in SQL Server where I would select something into a temporary table, that I can then use in another select statement.
CREATE OR ALTER PROCEDURE Procname
AS
BEGIN
SELECT
Somewhere.Col_1,
Somewhere.Col_2
INTO
#Temptable
FROM
Somewhere Somewhere
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM
#Temptable Temptable
INNER JOIN
Somewhere_Else.Col_2 = Temptable.Col_2
END
When I execute this procedure I would get returned the final select query
How would I replicate this procedure in Postgresql?
I know that you can select into a temporary table, but I cannot seem to figure out how to use this table in the next select statement within the same procedure
Create a set returning function, there is no need for a temp table at all.
CREATE function Procname()
returns table(col_1 ???, col2 ???) --<< change data types here
AS
$$
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM Somewhere Temptable
INNER JOIN Somewhere_Else ON Somewhere_Else.Col_2 = Temptable.Col_2;
$$
language sql
stable;
But for such a simple statement, I would rather create a view.
set serveroutput on;
CREATE OR REPLACE PROCEDURE test_migrate
(
--v_into_table dba_tables.schema#dbprd%TYPE,
--v_from_table dba_tables.table#dbprd%TYPE,
v_gid IN NUMBER
)
IS
BEGIN
select * INTO fx.T_RX_TXN_PLAN
FROM fx.T_RX_TXN_PLAN#dbprd
WHERE gid = v_gid;
--and schema = v_into_table
--and table = v_from_table;
COMMIT;
END;
I thought that SELECT * INTO would create a table in the new database from #dbprd. However, the primary issue is just being able to set these as variables and the goal is to EXEC(INTO_Table,FROM_Table,V_GID) to run the above code.
Error(9,19): PLS-00201: identifier 'fx.T_RX_TXN_PLAN' must be
declared Error(10,5): PL/SQL: ORA-00904: : invalid identifier
If your goal is to copy data from table in "another" database into a table that resides in "this" database (regarding database link you used), then it it INSERT INTO, not SELECT INTO.
For example:
CREATE OR REPLACE PROCEDURE test_migrate (v_gid in number)
IS
BEGIN
insert into fx.t_rx_txn_plan (col1, col2, ..., coln)
select col1, col2, ..., coln
from fx.t_rx_txn_plan#dbprod
where gid = v_gid;
END;
Last sentence you wrote looks like you'd want to make it dynamic, i.e. pass table names and v_gid (whatever that might be; looks like all tables that should be involved into this process have it). That isn't a simple task.
If you plan to use insert into select * from, that's OK but not for production system. What if someone alters a table and adds (or drops) a column or two? Your procedure will automatically fail. Correct way to do it is to enumerate all columns involved, but that requires fetching data from user_tab_columns (or all_ or dba_ version of the same), which complicates it even more.
Therefore, if you want to move data from here to there, why don't you do it using Data Pump Export & Import? Those utilities are designed for such a purpose, and will do the job better than your procedure. At least, I think so.
This way you should be returning a row. If so, add an OUT type parameter to the procedure with
CREATE OR REPLACE PROCEDURE test_migrate(
--v_into_table dba_tables.schema#dbprd%TYPE,
--v_from_table dba_tables.table#dbprd%TYPE,
i_gid IN NUMBER,
o_RX_TXN_PLAN OUT fx.T_RX_TXN_PLAN#dbprd%rowtype
) IS
BEGIN
SELECT *
INTO RT_RX_TXN_PLAN
FROM fx.T_RX_TXN_PLAN#dbprd
WHERE id = v_gid;
--and schema = v_into_table
--and table = v_from_table;
END;
and call the procedure such as
declare
v_rx_txn_plan fx.T_RX_TXN_PLAN#dbprd%rowtype;
v_gid number:=5345;
begin
test_migrate(v_gid => v_gid, rt_rx_txn_plan => v_rx_txn_plan);
dbms_output.put_line(v_rx_txn_plan.col1);
dbms_output.put_line(v_rx_txn_plan.col2);
end;
to print out the returning values for some columns of the table. to be able to create a new table from this, not SELECT * INTO ... syntax, but
CREATE TABLE T_RX_TXN_PLAN AS
SELECT *
INTO RT_RX_TXN_PLAN
FROM fx.T_RX_TXN_PLAN#dbprd
WHERE ...
is used.
But neither of the cases to issue a COMMIT since there's no DML exists within them.
To create a table you must use the CREATE TABLE statement, and to use any DDL statement in PL/SQL you have to use EXECUTE IMMEDIATE:
CREATE OR REPLACE PROCEDURE test_migrate
(
v_gid IN NUMBER
)
IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE FX.T_RX_TXN_PLAN AS
SELECT *
FROM fx.T_RX_TXN_PLAN#dbprd
WHERE gid = :GID'
USING IN v_gid;
END;
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.
SELECT Val from storedp_Value within the query editor of SQL Server Management Studio, is this possible?
UPDATE
I tried to create a temp table but it didn't seem to work hence why I asked here.
CREATE TABLE #Result
(
batchno_seq_no int
)
INSERT #Result EXEC storedp_UPDATEBATCH
SELECT * from #Result
DROP TABLE #Result
RETURN
Stored Procedure UpdateBatch
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
What am I doing wrong and how do I call it from the query window?
UPDATE #2
Ok, I'd appreciate help on this one, direction or anything - this is what I'm trying to achieve.
select batchno_seq from (delete from batchno_seq;insert into batchno_seq default values;
select * from batchno_seq) BATCHNO
INTO TEMP_DW_EKSTICKER_CLASSIC
This is part of a larger select statement. Any help would be much appreciated. Essentially this SQL is broken as we've migrated for Oracle.
Well, no. To select from a stored procedure you can do the following:
declare #t table (
-- columns that are returned here
);
insert into #t(<column list here>)
exec('storedp_Value');
If you are using the results from a stored procedure in this way and you wrote the stored procedure, seriously consider changing the code to be a view or user defined function. In many cases, you can replace such code with a simpler, better suited construct.
This is not possible in sql server, you can insert the results into a temp table and then further query that
CREATE TABLE #temp ( /* columns */ )
INSERT INTO #temp ( /* columns */ )
EXEC sp_MyStoredProc
SELECT * FROM #temp
WHERE 1=1
DROP TABLE #temp
Or you can use OPENQUERY but this requires setting up a linked server, the SQL is
SELECT * FROM (ThisServer, 'Database.Schema.ProcedureName <params>')
The best article (in my opinion) about all possible methods for sharing data between stored procedures in SQL Server you can find here: http://www.sommarskog.se/share_data.html
Try this
Change 'Return'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
to 'Select'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
SELECT #batchno_seq
My approach
select * into new_table from (select t1.col1,t1.col2,..
from table1 t1
union
select t2.cola,t2.colb,..
from table2 t2) as union_table
I MUST be missing something.
Since your stored procedure does not return a result set, and instead returns an integer, using the RETURN functionality of stored procs, you simply CANNOT INSERT into ANY table (since there isn't any result set coming back, at all).
BUT, you can (assuming that this is done iteratively, and not over a set) simply store the return value into a local variable, and insert that variable's value into whatever table is necessary.
However, if you simply want to return the value in the results of a Query Window in SSMS, doing the INSERT and SELECTING is overkill.
It seems to me like THIS would suffice (in a query window):
DECLARE #RetVal INT = 0;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
EXEC #RetVal = storedp_UPDATEBATCH;
COMMIT TRANSACTION;
SELECT #RetVal;
--OR
--PRINT #RetVal;
If this is way far off base, please provide the DDL for "batchno_seq", maybe I can be of better assistance that way.
Cheers!
select top 0 * INTO #temp from stored procedure
Need to create temp table based on the structure of data type returned from stored procedure.
Using sql server 2000,2005, 0r 2008
You can't do this. To get the results from a stored procedure, you have to first define the structure of the results:
create table #temp ( . . . );
insert into #temp
exec(stored procedure)
If you examine the syntax for the SELECT statement (here), you'll see no reference to running a stored procedure.
Perhaps you should post another question describing what you are trying to do. Why would a stored procedure be returning different result formats?