I am looking at this tutorial
and it confuses me as I don't get the SP
CREATE PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](#UpdatedProdData nText)
AS
DECLARE #hDoc int
exec sp_xml_preparedocument #hDoc OUTPUT,#UpdatedProdData
INSERT INTO TBL_TEST_TEST(NAME)
SELECT XMLProdTable.NAME
FROM OPENXML(#hDoc, 'ArrayOfTBL_TEST_TEST/TBL_TEST_TEST', 2)
WITH (
ID Int,
NAME varchar(100)
) XMLProdTable
EXEC sp_xml_removedocument #hDoc
First I am using SQL 2005 and do I need to install something on the server to get OPENXML to work? Next I don't get what these statements do
// not sure what #hDoc is for and why it is an int
DECLARE #hDoc int
// don't get what this is and where the output is.
exec sp_xml_preparedocument #hDoc OUTPUT,#UpdatedProdData
// don't get why it is "XMLProdTable" and if it always has to be like this
SELECT XMLProdTable.NAME
// pretty muct don't get anything what is happening after OPENXML
FROM OPENXML(#hDoc, 'ArrayOfTBL_TEST_TEST/TBL_TEST_TEST', 2)
WITH (
ID Int,
NAME varchar(100)
) XMLProdTable
// Don't know what this is really executing
EXEC sp_xml_removedocument #hDoc
Thanks
// not sure what #hDoc is for and why
it is an int DECLARE #hDoc int
That will be used in the next call, it is an output parameter
// don't get what this is and where
the output is. exec
sp_xml_preparedocument #hDoc
OUTPUT,#UpdatedProdData
It is calling the sp_xml_preparedocument, output just means it is an output parameter, #hDoc will be populated with the value in the proc
// don't get why it is "XMLProdTable"
and if it always has to be like this
SELECT XMLProdTable.NAME
XMLProdTable is the alias used in the next part, the CTE is named XMLProdTable
// pretty muct don't get anything what
is happening after OPENXML FROM
OPENXML(#hDoc,
'ArrayOfTBL_TEST_TEST/TBL_TEST_TEST',
2)
WITH (
ID Int,
NAME varchar(100)
) XMLProdTable --alias
It populates the CTE with values from the XML document under the ArrayOfTBL_TEST_TEST/TBL_TEST_TEST tag
// Don't know what this is really
executing EXEC sp_xml_removedocument
#hDoc
This is releasing the document from memory
Take a look at the samples here http://msdn.microsoft.com/en-us/library/ms186918.aspx
Related
I'm looking for help with a stored procedure in teradata. I want to update a whole table and for this I'm trying to use a for loop cursor. the problem is that my update is defined via column names passing through parameters to the SP.
I've seen it can be possible to use dynamic sql to do that but I haven't found any information on the subject concerning for loop cursor and dynamic sql. Is it possible with FOR LOOP CURSOR ?
I've tried to do only the select and calculs with dynamic sql, it works fine but then the problem is to update the table from the cursor on the select. In this case how to update a table from my cursor?
I let you show my code.
loop cursor :
REPLACE PROCEDURE [database].calDELAI
(
IN dateDebut VARCHAR(30),
IN dateFin VARCHAR(30),
IN delay VARCHAR(30)
)
BEGIN
DECLARE DATE_DEBUT_COLONNE VARCHAR(64);
DECLARE DATE_FIN_COLONNE VARCHAR(64);
SET DATE_DEBUT_COLONNE=dateDebut;
SET DATE_FIN_COLONNE=dateFin;
FOR for_loop_update AS cur_select_set CURSOR FOR
SELECT
TMP.DATE_FIN_COLONNE-TMP.DATE_DEBUT_COLONNE
FROM [database].ORD_T_DETL_ORDR_DELAI AS TMP
/* the select is more complicated but here is the spirit of it.*/
DO
IF (delay='DELAI1') THEN SET DELAI1=NB_JR_OUVRABLE;
END IF;
END FOR ;
END ;
The errors given by teradata are :
SPL1027:E, Missing/Invalid SQL statement'E(3810):Column/Parameter '[database].TMP.DATE_FIN_COLONNE' does not exist.'.
SPL2001:E, Undefined symbol 'DELAI1'.
SPL2001:E, Undefined symbol 'NB_JR_OUVRABLE'.
Thanks in advance for your replies and your help.
The call statement should contain all the input Paramenters , make sure you are specifying all the input parameters correctly. Could you please provide your call statement.
I cannot run the following SP
CREATE PROCEDURE SP_NYANSAT(
FORNAVN VARCHAR(30),
EFTERNAVN VARCHAR(30),
ADRESSE VARCHAR(50),
POSTNUMMER CHAR(4),
TELEFONNUMMER CHAR(8),
EMAIL VARCHAR(50))
AS
DECLARE VARIABLE ID INTEGER;
BEGIN
ID = GEN_ID(GEN_ANSAT_ID,1);
INSERT INTO MYTABLE (ID, FORNAVN, EFTERNAVN, ADRESSE, POSTNUMMER, TELEFONNUMMER, EMAIL) VALUES (:ID, :FORNAVN, :EFTERNAVN, :ADRESSE, :POSTNUMMER, :TELEFONNUMMER, :EMAIL);
END
The error I get is the following:
can't format message 13:896 -- message file C:\Windows\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 3, column 1.
CREATE.
Have you used Set Term before and after this code?
All commands in Firebird must be terminated with a semi-colon. If you want to create a stored procedure you need to be able to distinguish between the terminating semi-colon from the semi-colons inside the stored procedure.
Something like this:
SET TERM ^ ;
CREATE PROCEDURE SP_NYANSAT(
FORNAVN VARCHAR(30),
EFTERNAVN VARCHAR(30),
ADRESSE VARCHAR(50),
POSTNUMMER CHAR(4),
TELEFONNUMMER CHAR(8),
EMAIL VARCHAR(50))
AS
DECLARE VARIABLE ID INTEGER;
BEGIN
ID = GEN_ID(GEN_ANSAT_ID,1);
INSERT INTO MYTABLE (ID, FORNAVN, EFTERNAVN, ADRESSE, POSTNUMMER, TELEFONNUMMER, EMAIL) VALUES (:ID, :FORNAVN, :EFTERNAVN, :ADRESSE, :POSTNUMMER, :TELEFONNUMMER, :EMAIL);
END
^
SET TERM ; ^
Please notice how the declaration of the stored procedure is terminated with ^, thus ending the statement. After the declaration you also restore the terminating semi-colon.
On a side note, I would recommend to copy firebird.msg to the location the error you get tells you so you can see what is really happening.
EDIT:
If you wish you can check this link. There you can find a lot of information regarding Firebird + IBExpress, including SET TERM (page 81).
EDIT 2:
Just tried at home with IBExperts + Firebird and I had no problem creating the stored procedure. My guess is you are trying to do one of the following things:
You have opened an SQL editor and are trying to compile the code directly. That will not work because IBExperts thinks you are trying to run DSQL sentences. Stored procedures are created with PSQL sentences.
You are trying to use the "New procedure" utility (check buttons in the upper right side of the main menu) and pasted the whole code into the editor. That will not work because in that editor you only have to put the body code. Stored procedure name is set in a field on the upper right side of the window you opened. Parameters and variables are introduced by using the "Insert Parameter/Variable" button on the left side above the code editor. The SET TERM sentences are created automatically by IBExperts. You can check the resulting code in the DDL tab.
HTH
I really like SQuirreL SQL as a SQL query tool, but I've never been able to get it to call stored procedures in our AS/400 DB2 database. I always get the error "The number of parameter values set or registered does not match the number of parameters." I've double-checked the number of params and had no luck. This is the syntax I've tried for a procedure that takes one IN and one OUT:
call SOMESPROC(12345, ?);
It seems that SQuirrel currently is not capable of doing that on AS/400 DB2.
Using the open source "SQL Workbench/J" (http://www.sql-workbench.net/) I was able to call a procedure:
wbcall SOMESPROC(12345, ?);
It has its own command for calling a procedure "wbcall". Use ? for out parameters.
Note: While installing SQL Workbench/J make sure to download the right DB2 driver from IBM and also add the licence file while adding the driver inside SQL Workbench/J.
In Squirrel you can use something like this. You'll want to make sure the type of the declared variable matches the type of your out parameter in the stored procedure.
BEGIN
DECLARE outParam INT;
STORED_PROC_NAME(outParam);
END
If you also need to provide input for the procedure you could do this.
BEGIN
DECLARE outParam INT;
STORED_PROC_NAME('input', outParam);
END
You also need to change the statement separator to something other than ;. Otherwise it will break up the statement and try to send each piece individually.
In the pro version of DbVisualizer, with the "Process Parameter Markers in SQL" under the SQL Commander menu option enabled, it will allow the "?" param
call SOMESPROC(12345, ?);
through trial and error, I was able to see the results in Squirrel.
create or replace variable var4 char(1);
create or replace variable var5 decimal(3,0);
create or replace variable var6 char(60);
call getthedata('XXX',123456789,'1234567',var4,var5,var6);
select var4,var5,var6 from sysibm.sysdummy1; -- displays OUT parms
I would think that if there is one in then the call should be:
CALL SomeSProc(12345)
to get a result maybe try:
SELECT * FROM SomeSProc(12345)
Here is an tested example which works on Squirrel 3.7 with a db2 stored procedure . The trick is to passe with an transitional stored procedure MY_PROC_TEST to call the real stored procedure PROC_TEST.
change statement separator in squirrel > session > session properties > SQL : #
DROP PROCEDURE MY_PROC_TEST()#
CREATE PROCEDURE MY_PROC_TEST()
RESULT SETS 1 -- out resultset (call product)
LANGUAGE SQL
BEGIN
DECLARE flag SMALLINT; -- out parameter
CALL MY_PROC('2015', flag);
END #
CALL MY_PROC_TEST()#
END #
Then you can call the sored procedure like this :
CALL MY_PROC_TEST()#
This will work in Squirrel if you change the delimiter (as specified above). However, to see what the variable is, you need to do the following...
In my example, I will set the delimiter to a tildy (~). Include after last "end", before "select". Code begins here...
begin
declare inoutParm numeric(2,0);
call spMyStoredProcedure(
1234567
, inoutParm
);
declare global temporary table session.myTempTbl
(MyResult char(1024) )
with replace ;
insert into session.myTempTbl
(myResult)
values(inoutParm) ;
end
~
select myResult from session.myTempTbl
Mic Keeley
as400(db2) SQL Developer
I was able to cobble together some amalgamation of all of the above answers and came up with this which worked for me. I'm using Squirrel SQL 2018 connecting to an IBM AS/400 DB2 database. I did have to declare a statement separator, I used "#".
BEGIN
DECLARE success CHAR(1); -- output parameters
DECLARE message CHAR(300);
SET success = ' ';
SET message = ' ';
CALL myProc('some', 'params', 4, success, message);
DECLARE GLOBAL TEMPORARY TABLE session.myTmp(s_res CHAR(1), m_res CHAR(300)) WITH REPLACE;
INSERT INTO session.myTmp(s_res, m_res) VALUES(success, message);
END
# -- <- statement separator needs to be set to something other than ";" in this case it's set to "#"
SELECT * FROM session.myTmp;
change statement separator in squirrel > session > session properties > SQL : '#'
BEGIN
DECLARE inOutParam varchar(200);
set inOutParam = 'a value';
STORED_PROC_NAME(outParam);
END;
#
We are developing a migrate program. There are nearly 80 million records are there in DB. The code is as follows:
static int mymigration(struct progargs *args)
{
exec sql begin declare section;
const char *selectQuery;
const char *updateQuery;
long cur_start;
long cur_end;
long serial;
long number;
char frequency[3];
exec sql end declare section;
selectQuery = "select * from mytable where number >= ? and number <= ? for update of frequency ,status";
updateQuery = "update mytable set frequency = ?, "
" status = ? "
" where current of my_cursor";
cur_start= args->start;
cur_end = args->end;
exec sql prepare my_select_query from :selectQuery;
/* Verify the sql code for error here */
exec sql declare my_select_cursor cursor with hold for my_select_query;
exec sql open my_select_cursor using :cur_start, :cur_end;
/* Verify the sql code for error here */
exec sql prepare my_update_query from :updateQuery;
/* Verify the sql code for error here */
while (1)
{
number = 0;
serial = 0;
memset(frequency,0,sizeof(frequency));
exec sql fetch my_select_cursor into number,:serial,:frequency;
if (sqlca.sqlcode != SQL_OK)
break;
exec sql execute my_update_query using :frequency, :frequency;
}
exec sql close my_select_trade_cursor;
}
While implementing this, we are getting the error message "-255". We found one solution as to add being work and commit work. Since we have large amount of data, this might clutter the transaction log.
Is there any other solution available for this problem? The IBM website for informix shows the usage is correct.
Appreciate the help in advance.
Thanks,
Mathew Liju
Error -255 is "Not in transaction".
I see no BEGIN WORK (or COMMIT WORK or ROLLBACK WORK) statements.
You need to add BEGIN WORK before you open the cursor with the FOR UPDATE clause. You then need to decide whether to commit periodically to avoid overlong transactions. The fact that you use a FOR HOLD cursor shows that you had thought about using sub-transactions; if you were not going to do so, you would not use that clause.
Note that Informix has 3 primary database logging modes:
Unlogged (no transaction support)
Logged (by default, each statement is a singleton transaction; an explicit BEGIN WORK starts a multi-statement transaction terminated by COMMIT WORK or ROLLBACK WORK).
Logged MODE ANSI (slightly simplistically, you are automatically in a transaction; you need an explicit COMMIT or ROLLBACK to terminate a transaction, and may then, optionally, use an explicit BEGIN, but the BEGIN is not actually necessary).
From the symptoms you describe, you have a logged but not MODE ANSI database. Therefore, you must explicitly code the BEGIN WORK statements.
Is the following possible:
EXEC sp_Edu3_DeleteTreeStructure (SELECT TreeStructureId FROM TreeStructures)
The SP normally takes one argument. What I want is that the SP is executed for each TreeStructureId found by the Query.
thx, Lieven Cardoen
You can use a CURSOR to do this.
DECLARE #treeStructureId int
DECLARE TreeStructureCursor CURSOR FOR
SELECT
TreeStructureId
FROM
TreeStructures
OPEN TreeStructureCursor
FETCH NEXT FROM TreeStructureCursor
INTO #treeStructureId
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_Edu3_DeleteTreeStructure(#treeStructureId)
FETCH NEXT FROM TreeStructureCursor
INTO #treeStructureId
END
CLOSE TreeStructureCursor
DEALLOCATE TreeStructureCursor