Loop cursor variable in DB2 - db2

CREATE OR REPLACE PROCEDURE qqq ()
P1: BEGIN
Declare cID char(5) ;
Declare cc char(5) ;
Declare SQLSTATE char(5) default '00000' ;
declare stmt varchar(1000) ;
declare c1 cursor for s1 ;
set cid = 'b' ;
Set stmt = 'select * from aaa where a = ?' ;
prePare s1 from stmt ;
open c1 using cid ;
ins_loop :
Loop
fetch c1 into cc ;
if SQLSTATE <> '00000' then LEAVE ins_loop ; end if ;
insert into bbb (aa) values ('3' || cc) ;
end loop ins_loop;
close c1 ;
commit ;
END P1
After running,the table bbb is empty. IF it is correct, the table bbb has 2 rows. Because the query ( select * from aaa where a = 'b' ) has 2 rows.

You get SQLSTATE = 01503, if your table contains more than 1 column. It's a warning (not an exception), so your SP proceeds its execution.
Either use select column_name from ... or modify the SQLSTATE <> '00000' condition appropriately instead.
P.S.: don't use commit in your SP unless it's really necessarily. It doesn't matter in this case, but it's better, when calling application manages transactions.

Related

Trying to use temporary table in IBM DB2 and facing issues

I am getting the following error while creating a stored procedure for testing purpose:
SQL Error [42601]: An unexpected token "DECLARE GLOBAL TEMPORARY TABLE
SESSION" was found following "RSOR WITH RETURN FOR". Expected tokens may include: "".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.21.29
Code:
CREATE OR REPLACE PROCEDURE Test ( IN GE_OutPutType SMALLINT)
----------------------------------------------------------------------------------------------------
DYNAMIC RESULT SETS 1 LANGUAGE SQL
BEGIN
DECLARE C CURSOR WITH RETURN FOR DECLARE GLOBAL TEMPORARY TABLE
SESSION.TEMP (DATE CHAR(10) NOT NULL,
SALARY DECIMAL(9,
2) ,
COMM DECIMAL(9,
2));
INSERT
INTO
SESSION.TEMP (DATE,
SALARY,
COMM) SELECT
VARCHAR_FORMAT(CURRENT_DATE,
'MM/DD/YYYY'),
10.2,
11.5
FROM
sysibm.sysdummy1
IF GE_OutPutType = 1
BEGIN
SELECT
*
FROM
TEMP
ELSEIF GE_OutPutType = 2 SELECT
'HEADER' CONCAT SPACE(1979) CONCAT 'H'
FROM
sysibm.sysdummy1
END OPEN C;
END
Your syntax is not valid.
You must declare your temporary table independently of your cursor.
You cannot combine these in a single statement.
Use dynamic-SQL features to achieve what you need.
Use instead the format:
Declare c1 cursor with return to caller for Statement1
and
set v_cursor_text = 'select ... from session.temp ; `
then use
prepare Statement1 from v_cursor_text;
and before you exit the stored procedure you need to leave the cursor opened:
open c1;
Do study the Db2 online documentation to learn more about these features.
Here is a small fragment of your procedure showing what I mean:
CREATE OR REPLACE PROCEDURE mytest ( IN GE_OutPutType SMALLINT)
DYNAMIC RESULT SETS 1
LANGUAGE SQL
specific mytest
BEGIN
DECLARE v_cursor_text varchar(1024);
DECLARE C1 CURSOR WITH RETURN FOR Statement1;
DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP (
DATE CHAR(10) NOT NULL,
SALARY DECIMAL(9,
2) ,
COMM DECIMAL(9,
2))
with replace on commit preserve rows not logged;
INSERT INTO SESSION.TEMP (DATE, SALARY, COMM)
SELECT VARCHAR_FORMAT(CURRENT_DATE, 'MM/DD/YYYY'),
10.2,
11.5
FROM sysibm.sysdummy1 ;
if GE_OutPutType = 1
then
set v_cursor_text = 'select * from session.temp';
end if;
if GE_OutPutType = 2
then
set v_cursor_text = 'select ''header'' concat space(1979) concat ''H'' from sysibm.sysdummy1';
end if;
prepare Statement1 from v_cursor_text;
open c1;
END#

Why i am getting null values when i call to procedure in mysql?

delimiter $$
create procedure fp10 ( in d varchar(30),out di int)
begin
select id into di from a1 where department = d;
end $$
delimiter ;
call fp10('IT',#di);
select #di;

TFS 2013 Update 4 to TFS 2015 Update 3 Collection Error

Updating my TFS 2013 Update 4 collection to TFS 2015 Update 3. Using a backup of the production collection data in a DEV location. Did the backup with the production collection being detached. Didn't have any errors. The backup is 254GB.
This is the error currently stopping me from attaching the collection:
Msg 3732, Level 16, State 1, Line 93
Cannot drop type 'typ_ItemSpec2' because it is being referenced by object 'prc_QueryPendingChanges_MS'. There may be other objects that reference this type.
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE #status INT
DECLARE #procedureName SYSNAME = N'upd_VersionControlToDev14M80_PostSchema'
DECLARE #tfError NVARCHAR(255)
IF EXISTS (
SELECT *
FROM sys.triggers
WHERE name = 'trg_tbl_VCFirstRunProject'
)
BEGIN
DROP TRIGGER trg_tbl_VCFirstRunProject
END
IF EXISTS (
SELECT *
FROM sys.indexes
WHERE name = 'IX_tbl_VCFirstRunProject_OldServerItemPrefix'
AND object_id = OBJECT_ID('dbo.tbl_VCFirstRunProject')
)
BEGIN
-- Delete upgrade-only rows for $\, a few partitions at a time
-- We need dynamic SQL for this to be rerunnable.
EXEC #status = sp_executesql N'
DECLARE #batchStart INT = 1
DECLARE #batchEnd INT
DECLARE #end INT
DECLARE #batchSize INT = 50
-- Get the partition range
SELECT TOP (1)
#end = PartitionId
FROM tbl_VCFirstRunProject
ORDER BY PartitionId DESC
WHILE (#batchStart <= #end)
BEGIN
SET #batchEnd = #batchStart + #batchSize
DELETE tbl_VCFirstRunProject
WHERE PartitionId BETWEEN #batchStart AND #batchEnd
AND OldServerItemPrefix = N''''
OPTION (OPTIMIZE FOR (#batchStart=1, #batchEnd=50))
SET #batchStart = #batchEnd + 1
END
'
IF (#status <> 0)
BEGIN
SET #tfError = dbo.func_GetMessage(500004); RAISERROR(#tfError, 16, -1, #procedureName, #status, N'sp_executesql', N'DELETE tbl_VCFirstRunProject')
RETURN
END
DROP INDEX IX_tbl_VCFirstRunProject_OldServerItemPrefix ON tbl_VCFirstRunProject
END
IF EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = Object_ID(N'dbo.tbl_VCFirstRunProject', N'U')
AND name = N'OldServerItemPrefix'
)
BEGIN
ALTER TABLE tbl_VCFirstRunProject
DROP COLUMN OldServerItemPrefix, NewServerItemPrefix
END
IF TYPE_ID('dbo.typ_BranchObject2') IS NOT NULL
BEGIN
DROP TYPE typ_BranchObject2
END
IF TYPE_ID('dbo.typ_BuildMappingInput2') IS NOT NULL
BEGIN
DROP TYPE typ_BuildMappingInput2
END
IF TYPE_ID('dbo.typ_CreateLabelInput') IS NOT NULL
BEGIN
DROP TYPE typ_CreateLabelInput
END
IF TYPE_ID('dbo.typ_ExpandedChange2') IS NOT NULL
BEGIN
DROP TYPE typ_ExpandedChange2
END
IF TYPE_ID('dbo.typ_ItemSpec2') IS NOT NULL
BEGIN
DROP TYPE typ_ItemSpec2
END
IF TYPE_ID('dbo.typ_LocalPendingChange3') IS NOT NULL
BEGIN
DROP TYPE typ_LocalPendingChange3
END
IF TYPE_ID('dbo.typ_LocalVersion3') IS NOT NULL
BEGIN
DROP TYPE typ_LocalVersion3
END
IF TYPE_ID('dbo.typ_LockConflictCandidate2') IS NOT NULL
BEGIN
DROP TYPE typ_LockConflictCandidate2
END
IF TYPE_ID('dbo.typ_LockObject') IS NOT NULL
BEGIN
DROP TYPE typ_LockObject
END
IF TYPE_ID('dbo.typ_Mapping2') IS NOT NULL
BEGIN
DROP TYPE typ_Mapping2
END
IF TYPE_ID('dbo.typ_PendingAdd2') IS NOT NULL
BEGIN
DROP TYPE typ_PendingAdd2
END
IF TYPE_ID('dbo.typ_PendingChangeObject') IS NOT NULL
BEGIN
DROP TYPE typ_PendingChangeObject
END
IF TYPE_ID('dbo.typ_PendingChangeSecurity') IS NOT NULL
BEGIN
DROP TYPE typ_PendingChangeSecurity
END
IF TYPE_ID('dbo.typ_PendingMerge2') IS NOT NULL
BEGIN
DROP TYPE typ_PendingMerge2
END
IF TYPE_ID('dbo.typ_PendingPropertyChange2') IS NOT NULL
BEGIN
DROP TYPE typ_PendingPropertyChange2
END
IF TYPE_ID('dbo.typ_VersionedItemId') IS NOT NULL
BEGIN
DROP TYPE typ_VersionedItemId
END
None of the standard queries from Microsoft have _MS as a suffix. I suspect that someone hand-tweaked the original prc_QueryPendingChanges and left this around as a backup. In that case you should be able to drop this procedure and retry the upgrade.

How to delete column in all tables

I am use Firebird 2.5
I have multiple tables with column name 'col1', and I would like delete it.
I can use this statement:
DELETE FROM RDB$RELATION_FIELDS
WHERE RDB$FIELD_NAME = 'col1';
But I do not know is it safe.
I try to use execute block for multiple execute statements, but I do not know, how to combine it.
SET TERM ^ ;
EXECUTE BLOCK AS
DECLARE s AS VARCHAR(200)
BEGIN
WHILE (SELECT rf.RDB$RELATION_NAME FROM RDB$RELATION_FIELDS rf WHERE rf.RDB$FIELD_NAME = 'AKTYWNY';) DO
BEGIN
ALTER TABLE :s DROP c1;
END
END^
SET TERM ; ^
This is example how to do this in stored procedure :
create or alter procedure DELETE_COL (
F_COL char(31))
as
declare variable V_STAT varchar(256);
declare variable R_NAME char(31);
begin
for
select f.rdb$relation_name
from rdb$relation_fields f
join rdb$relations r on f.rdb$relation_name = r.rdb$relation_name
and r.rdb$view_blr is null
and (r.rdb$system_flag is null or r.rdb$system_flag = 0)
where f.rdb$field_name = :f_col
order by 1, f.rdb$field_position
into
:r_name -- Table Name
do
begin
v_stat = 'alter table ' || :r_name || ' drop ' || :f_col;
execute statement(v_stat); /*because alter table ... is not allowed here */
end
end
You can use this in execute block also.

Initialize a string in a stored function

I call this procedure without any problem :
SELECT SP_getGlobalVariable('current_user_id')::INT ;
If I call it inside another stored procedure like this :
-- Get current User Id --
SELECT SP_getGlobalVariable('current_user_id')::INT INTO __currentUserId ;
I have this error :
ERROR : Syntax error near "current_user_id"
LINE 25: SELECT SP_getGlobalVariable('current_user_id')::INT INTO _...
It is probably a stupid syntax error... If someone can help a poor MySQL user starting using PG !
EDIT 1 :
SELECT version();
PostgreSQL 9.3.3 on i686-pc-linux-gnu, compiled by gcc-4.4.real (Debian 4.4.5-8) 4.4.5, 32-bit
This is the result of the version() call.
CREATE OR REPLACE FUNCTION SP_getGlobalVariable (__variableName VARCHAR(64))
RETURNS VARCHAR
AS
'
DECLARE
BEGIN
RETURN (SELECT value FROM tmp_variables
WHERE name = __variableName) ;
END ;
'
LANGUAGE 'plpgsql';
The procedure to get the global variable in the temporary table.*
EDIT 2 :
CREATE OR REPLACE FUNCTION SP_insertSite (__siteName VARCHAR(70), __siteDescription TEXT, __siteLatitude NUMERIC, __siteLongitude NUMERIC)
RETURNS INT
AS
'
DECLARE
-- Variables
__right_edge_father INT ;
__left_edge_father INT ;
__depth_father INT ;
__nbrSites INT ;
__insertId INT ;
__currentUserId INT ;
BEGIN
-- Check if tree is empty --
SELECT COUNT(*) INTO __nbrSites
FROM site ;
-- Get current User Id --
SELECT SP_getGlobalVariable('current_user_id')::INT INTO __currentUserId ;
IF __nbrSites = 0 THEN
INSERT INTO site (site_name, site_description, site_latitude, site_longitude, site_left_edge, site_right_edge, site_depth, site_create_dt, site_create_user_id)
VALUES(__siteName, __siteDescription, 0.0, 0.0, 1, 2, 0, LOCALTIMESTAMP, __currentUserId)
RETURNING site_id INTO __insertId;
ELSE
-- Get father edges --
SELECT site_left_edge, site_right_edge, site_depth
INTO __left_edge_father, __right_edge_father, __depth_father
FROM site
WHERE site_id = (SELECT site_id FROM site WHERE site_depth = 0 LIMIT 1) ;
-- Updates left edges --
UPDATE site
SET site_left_edge = site_left_edge + 2
WHERE site_left_edge >= __right_edge_father ;
-- Updates right edges --
UPDATE site
SET site_right_edge = site_right_edge + 2
WHERE site_right_edge >= __right_edge_father ;
-- Insert new node --
INSERT INTO site (site_name, site_description, site_latitude, site_longitude, site_left_edge, site_right_edge, site_depth, site_create_dt, site_create_user_id)
VALUES(__siteName, __siteDescription, __siteLatitude, __siteLongitude, __right_edge_father, __right_edge_father+1, __depth_father+1, LOCALTIMESTAMP, __currentUserId)
RETURNING site_id INTO __insertId;
END IF ;
RETURN __insertId ;
END ;
'
LANGUAGE plpgsql;
The problem is that you are using single quotes to encapsulate the function body, and so, when you try to add single quotes inside the body, you need to escape it, for instance:
CREATE OR REPLACE FUNCTION SP_insertSite (...)
RETURNS INT
AS
'
DECLARE
...
-- Get current User Id --
SELECT SP_getGlobalVariable(''current_user_id'')::INT INTO __currentUserId ;
...
RETURN __insertId ;
END ;
'
LANGUAGE plpgsql;
That would work nice. But I recommend you to use dollar-quoting and so you don't have to worry with single-quote escaping inside the function body, as the following:
CREATE OR REPLACE FUNCTION SP_insertSite (...)
RETURNS INT
AS
$$
DECLARE
...
-- Get current User Id --
SELECT SP_getGlobalVariable('current_user_id')::INT INTO __currentUserId ;
...
RETURN __insertId ;
END ;
$$
LANGUAGE plpgsql;
I'd recommend you to read PostgreSQL docs about the usage of dollar-quoting in PL/pgSQL (the entire document, not just this sub-section is also interesting to read).