I am trying to get around a problem where the following SP locks the log table DWH_METADATA.LOG_TABLE and the lock is released only when the DELETE ALL and INSERT-SELECT statements are executed. This procedure chokes the whole ETL process. Moreover, this procedure is called via IBM Data Stage Sequence.
Below is the procedure code:
REPLACE PROCEDURE DWH.HIST_PROC (OUT RETURN_MSG VARCHAR(100))
BEGIN
/**********************************
* DECALRE VARIABLES *
**********************************/
DECLARE PJ_RID INTEGER;
DECLARE MS_Name VARCHAR(100);
DECLARE JS_Name VARCHAR(100);
DECLARE JT_Name VARCHAR(100);
DECLARE PJ_Domain VARCHAR(100);
DECLARE JS_Timestamp TIMESTAMP(0);
DECLARE Script_Name VARCHAR(500);
DECLARE Procedure_Name VARCHAR(100);
DECLARE JS_No INTEGER;
DECLARE SS_Ts TIMESTAMP(0);
DECLARE SR_Processed INTEGER;
/***********************************
* EXCEPTION HANDLING *
***********************************/
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
UPDATE DWH_METADATA.LOG_TABLE
SET
JOB_STATUS = SQLCODE,
STEP_END_TS = CURRENT_TIMESTAMP(0),
JOB_END_TIMESTAMP = CURRENT_TIMESTAMP(0)
WHERE JOB_RUN_ID = PJ_RID
AND STEP_NO = JS_No
AND JOB_NAME = JS_Name;
END;
/**********************************
* SET VARIABLES *
**********************************/
SET MS_Name = 'A Value';
SET JS_Name='A Value';
SET JT_Name = 'A Value';
SET PJ_Domain = 'A Value';
SET JS_Timestamp = CURRENT_TIMESTAMP(0);
SET Script_Name = 'A Value';
SET Procedure_Name = 'A Value';
SET SS_Ts = CURRENT_TIMESTAMP(0);
SET JS_No = 0;
SET RETURN_MSG = 'Failure';
--------------------------------------------------------
--Insert log for step 0
INSERT INTO DWH_METADATA.LOG_TABLE
(
DWH_METADATA.LOG_TABLE.JOB_RUN_ID,
DWH_METADATA.LOG_TABLE.STEP_NO,
DWH_METADATA.LOG_TABLE.MASTER_SEQ_NAME ,
DWH_METADATA.LOG_TABLE.JOB_NAME ,
DWH_METADATA.LOG_TABLE.TABLE_NAME,
DWH_METADATA.LOG_TABLE.JS_Timestamp ,
DWH_METADATA.LOG_TABLE.JOB_END_TIMESTAMP ,
DWH_METADATA.LOG_TABLE.SS_Ts ,
DWH_METADATA.LOG_TABLE.STEP_END_TS ,
DWH_METADATA.LOG_TABLE.JOB_STATUS ,
DWH_METADATA.LOG_TABLE.JOB_DOMAIN ,
DWH_METADATA.LOG_TABLE.SCRIPT_NAME ,
DWH_METADATA.LOG_TABLE.PROCEDURE_NAME ,
DWH_METADATA.LOG_TABLE.RECORDS_PROCESSED
)
VALUES
(:PJ_RID, :JS_No, :MS_Name, :JS_Name, :JT_Name,
:JS_Timestamp, NULL, :SS_Ts, NULL, NULL, :PJ_Domain, :Script_Name, :Procedure_Name, NULL
);
-----------------------------------------------------------------------------------------------------------------
LOCKING ROW FOR ACCESS
SEL COALESCE(MAX(JOB_RUN_ID),0) + 1
FROM DWH_METADATA.LOG_TABLE
WHERE JOB_NAME = :JS_Name
AND Job_Domain = :PJ_Domain
INTO :PJ_RID;
/********************************** DELETE/INSERT RTD_DATA *************************************************/
--Insert log for step 1
SET JS_No = JS_No + 1 ;
SET JT_Name = 'DWH.HISTORY_TABLE ';
SET SS_Ts = CURRENT_TIMESTAMP(0);
INSERT INTO DWH_METADATA.LOG_TABLE
VALUES( :PJ_RID, :JS_No, :MS_Name, :JS_Name, :JT_Name, :JS_Timestamp,
NULL, :SS_Ts, NULL, NULL, :PJ_Domain, :Script_Name, :Procedure_Name, NULL);
DELETE FROM DWH.HISTORY_TABLE ALL;
INSERT INTO DWH.HISTORY_TABLE
(
COLUMNLIST
)
SELECT
SI.COLUMNS,
S2.COLUMNS,
.
.
.
FROM SOMETABLE1 S1
INNER JOIN SOMETABLE2 S2
ON S1.ID = S2.ID
.
.
.
.;
--Update log for step 1
SET SR_Processed = ACTIVITY_COUNT;
UPDATE DWH_METADATA.LOG_TABLE
SET
JOB_STATUS = SQLCODE,
STEP_END_TS = CURRENT_TIMESTAMP(0),
JOB_END_TIMESTAMP = CURRENT_TIMESTAMP(0),
RECORDS_PROCESSED = :SR_Processed
WHERE JOB_RUN_ID = PJ_RID
AND STEP_NO = JS_No
AND JOB_DOMAIN = PJ_Domain
AND PROCEDURE_NAME = Procedure_Name
AND "TABLE_NAME"=JT_Name;
---------------------------------------------------------------------------------------
SET RETURN_MSG = 'Success' ;
END;
Based on same logic, many other stored procedures are executing on daily basis without any such issue. I am unable to understand, why this procedure locks the log table although both of its' insert statements have been executed.
I have tried to execute the individual DML statements in BT and ET, and doing such did not have any impact and the issue persisted. Moreover, I have optimized the underlying INSERT-SELECT. It has reduced the exeution time significantly but the locking is still occurring.
Anyone please, help me pinpoint why this issue is ocurring.
EDIT: Structure of log table.
CREATE MULTISET TABLE DWH_METADATA.LOG_TABLE ,FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO,
MAP = TD_MAP1
(
JOB_RUN_ID INTEGER,
STEP_NO INTEGER,
MASTER_SEQ_NAME VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC,
JOB_NAME VARCHAR(200) CHARACTER SET LATIN NOT CASESPECIFIC,
TABLE_NAME VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC,
JOB_START_TIMESTAMP TIMESTAMP(6),
JOB_END_TIMESTAMP TIMESTAMP(6),
STEP_START_TS TIMESTAMP(0),
STEP_END_TS TIMESTAMP(0),
JOB_STATUS INTEGER,
JOB_DOMAIN VARCHAR(200) CHARACTER SET LATIN NOT CASESPECIFIC,
SCRIPT_NAME VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
PROCEDURE_NAME VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
RECORDS_PROCESSED DECIMAL(18,0))
PRIMARY INDEX ( JOB_NAME ,TABLE_NAME ,JOB_START_TIMESTAMP );
Related
I attempt to create a procedure or function to populate a table name Time_Dim in MariaDB.
DELIMITER /
CREATE FUNCTION filltimeDim ()
BEGIN
DECLARE vQuarter VARCHAR(6);
DECLARE vMonth_Name VARCHAR(20);
DECLARE vdate_id date;
DECLARE vyear_id CHAR(4);
DECLARE vweekly_Name VARCHAR(20);
DECLARE vMonth_Num TINYINT(10);
DECLARE vweekday_Num TINYINT(10);
BEGIN
SET vdate_id = CONVERT('1998-01-01', DATE);
WHILE (CONVERT('vdate_id' USING utf8) <= '2002-12-31')
LOOP
SET vyear_id = YEAR(vdate_id);
SET vQuarter = QUARTER(vdate_id);
SET vMonth_Name = MONTHNAME(vdate_id);
SET vweekly_Name = DAYOFWEEK(vdate_id);
SET vMonth_Num = MONTH(vdate_id);
SET vweekday_Num = WEEKDAY(vdate_id);
INSERT INTO Time_Dim VALUES
(vdate_id, vyear_id, vquarter, vMonth_Name,vweekly_Name,vMonth_Num,vweekday_Num);
SET vdate_id = vdate_id + 1;
END LOOP;
END;
END; /
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
SET vyear_id = YEAR(vdate_id);
SET vQuarter = QUA' at line 13
The syntax for while in MariaDB is:
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
https://mariadb.com/kb/en/library/while/
You shouldn't use the 'LOOP' keywords
You can use Sequence Storage Engine:
-- SELECT
-- DATEDIFF('2002-12-31', '1990-01-01'); -- 4747
INSERT INTO `Time_Dim` (
`vdate_id`,
`vyear_id`,
`vquarter`,
`vMonth_Name`,
`vweekly_Name`,
`vMonth_Num`,
`vweekday_Num`
)
SELECT
`der`.`day`,
YEAR(`der`.`day`),
QUARTER(`der`.`day`),
MONTHNAME(`der`.`day`),
DAYOFWEEK(`der`.`day`),
MONTH(`der`.`day`),
WEEKDAY(`der`.`day`)
FROM (
SELECT
'1990-01-01' + INTERVAL (`seq`) DAY `day`
FROM
`seq_0_to_4747`
) `der`;
See dbfiddle.
I am trying to insert asp.net grid data to database table [DBO].[tbl_family_member]. I've created a type typ_fam_mem for this. But the problem is the column family_member_id value is generated from another table [DBO].[TBL_FAMILY_HEAD]. Please look at the procedure.
How can I insert data to the table from a datatable and procedure variables?
CREATE TABLE [DBO].[tbl_family_member]
(
family_member_id bigint identity(1,1) not null,
family_head_id bigint NOT NULL,
mem_name nvarchar(200) not null,
mem_gender tinyint not null,
mem_occupation nvarchar(50),
mem_maritial_status tinyint,
STATUS INT NOT NULL DEFAULT '1',
CONSTRAINT pk_family_member PRIMARY KEY (family_member_id)
)
create type typ_fam_mem as table
(
mem_name nvarchar(200) not null,
mem_gender tinyint not null,
mem_occupation nvarchar(50),
mem_maritial_status tinyint
)
Stored procedure
CREATE PROCEDURE [dbo].[P_SET_PROFILE_REGISTRATION]
(
--- FOR FAMILY HEAD TABLE
#P_NAME NVARCHAR(200),
#P_GENDER TINYINT,
---- FOR FAMILY MEMBER
#P_FAMILY_DT DBO.typ_fam_mem READONLY,
#V_OUT TINYINT OUTPUT
)
AS
DECLARE #FAMILY_HEAD_ID BIGINT;
BEGIN
SET NOCOUNT ON;
BEGIN TRY
INSERT INTO [DBO].[TBL_FAMILY_HEAD] ([NAME], [GENDER])
VALUES (#P_NAME, #P_GENDER)
SET #FAMILY_HEAD_ID = SCOPE_IDENTITY();
IF ##ROWCOUNT > 0
BEGIN
--- block for inserting data into [DBO].[tbl_family_member]
END
END TRY
BEGIN CATCH
END CATCH
END
#P_FAMILY_DT is a table type, you can query the table type like a normal table.
Your insert should look like
INSERT INTO [DBO].[tbl_family_member]
(family_head_id,
mem_name,
mem_gender,
mem_occupationm,
mem_maritial_status)
SELECT #FAMILY_HEAD_ID,
mem_name,
mem_gender,
mem_occupation,
mem_maritial_status
FROM #P_FAMILY_DT
You can use INSERT...SELECT, specifying the variable with the generated value. The example below also adds a transaction management (appropriate for multi-table inserts unless client app manages the transaction) and error handling.
CREATE PROCEDURE [dbo].[P_SET_PROFILE_REGISTRATION]
--- FOR FAMILY HEAD TABLE
#P_NAME NVARCHAR(200),
#P_GENDER TINYINT,
---- FOR FAMILY MEMBER
#P_FAMILY_DT DBO.typ_fam_mem READONLY,
#V_OUT TINYINT OUTPUT
AS
DECLARE #FAMILY_HEAD_ID BIGINT;
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRAN;
INSERT INTO [DBO].[TBL_FAMILY_HEAD] ([NAME], [GENDER])
VALUES (#P_NAME, #P_GENDER)
SET #FAMILY_HEAD_ID = SCOPE_IDENTITY();
INSERT INTO dbo.tbl_family_member(
mem_name
, mem_gender
, mem_occupation
, mem_maritial_status
, family_head_id
)
SELECT
mem_name
, mem_gender
, mem_occupation
, mem_maritial_status
, #FAMILY_HEAD_ID
FROM #P_FAMILY_DT;
COMMIT;
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
GO
I am trying to develop web application based on tutorial example. I have created procedure cilveki_list which has many parameters. When I compile this code I get two errors:
1)PL/SQL: SQL Statement ignored
2)PL/SQL: ORA-00933: SQL command not properly ended
First error refers to line 'c_kods in varchar2 default null'
and the second one to line ' if p_action = 'INSERT' then'.
Proedure behaviour depends on the parameter 'p_action', if it is set to 'INSERT', then insertion is perfomed, if it is set to 'UPDATE', then table update is performed.
But what is wrong with porcedue, why I get those errors, when I try to compile it?
create or replace package PACKAGE2 is
procedure cilveki_list(
c_vards in char default null,
c_uzvards in char default null,
c_dzimsanas_gads in number default null,
c_kods in varchar2 default null,
p_action in varchar2 default 'DISPLAY');
end PACKAGE2;
/
create or replace package body PACKAGE2 is
procedure cilveki_list(
c_vards in char default null,
c_uzvards in char default null,
c_dzimsanas_gads in number default null,
c_kods in varchar2 default null,
p_action in varchar2 default 'DISPLAY')
is
l_count number := 0;
begin
if p_action = 'INSERT' then
insert into CILVEKI
values ('',c_vards,c_uzvards,c_dzimsanas_gads,c_kods);
commit;
elsif p_action = 'UPDATE' then
UPDATE CILVEKI
set VARDS = c_vards,
UZVARDS = c_uzvards,
DZIMSANAS_GADS = c_dzimsanas_gads
WHERE PERS_KODS = c_kods;
commit;
end if;
htp.htmlOpen;
htp.bodyOpen;
htp.tableOpen;
htp.tableRowOpen;
htp.tableHeader('VARDS');
htp.tableHeader('UZVARDS');
htp.tableHeader('DZIMSANAS_GADS');
htp.tableHeader('PERS_KODS');
htp.tableRowClose;
for c1 in (select VARDS, UZVARDS, DZIMSANAS_GADS,PERS_KODS
from CILVEKI
order by UZVARDS) loop
htp.tableRowOpen;
htp.tableData(
htf.anchor(
curl => 'cilveki_modify?p_action=UPDATE&p_ticker=' || c1.VARDS,
ctext => c1.VARDS) );
htp.tableData( c1.UZVARDS );
htp.tableData( c1.DZIMSANAS_GADS );
htp.tableData( c1.PERS_KODS );
htp.tableRowClose;
l_count := l_count + 1;
end loop;
htp.tableClose;
htp.p( l_count || ' rows found');
htp.anchor( curl => 'cilveki_modify?p_action=INSERT',
ctext => 'Create New' );
htp.bodyClose;
htp.htmlClose;
end cilveki_list;
end PACKAGE2;
/
UPDATE CILVEKI
set VARDS = c_vards,
UZVARDS = c_uzvards,
DZIMSANAS_GADS = c_dzimsanas_gads,
WHERE PERS_KODS = c_kods
commit;
4th line above appears to be invalid. There shouldn't be a comma at the end of the line. Please remove the comma and re-compile the code.
public DataSet ViewQuizDetails(List<string> name)
{
DataSet dsGrades = null;
var dbCon = new DBConnection("Quiz");
foreach(string val in name)
{
dbCon.AddParameter("#name", val);
dsGrades = dbCon.Execute_DataSet("spViewQuizDetails", null);
}
return dsGrades;
}
ALTER PROCEDURE [dbo].[spViewQuizDetails]
-- Add the parameters for the stored procedure here
#name varchar(30)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
--SELECT * FROM QuizDetails INNER JOIN Elearning
--ON QuizDetails.ElearningId=Elearning.ElearningId ;
SELECT *
FROM QuizDetails INNER JOIN Elearning
ON QuizDetails.ElearningId=Elearning.ElearningId where ElearningName=#name
END
When I pass multiple values I'm getting the following error.
Error received: Procedure or function spViewQuizDetails has too many arguments
specified.
Pass your stored procedure a parameter with names concatinated .
Build this concatinated name string in your C# code
Declare #Name VARCHAR(1000) = 'Name1,Name2,Name3';
ALTER PROCEDURE [dbo].[spViewQuizDetails]
-- Add the parameters for the stored procedure here
#name VARCHAR(1000)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #xml xml;
set #xml = N'<root><r>' + replace(#name,',','</r><r>') + '</r></root>'
-- Insert statements for procedure here
--SELECT * FROM QuizDetails INNER JOIN Elearning ON QuizDetails.ElearningId=Elearning.ElearningId ;
SELECT * FROM QuizDetails
INNER JOIN Elearning
ON QuizDetails.ElearningId = Elearning.ElearningId
where ElearningName IN (select t.value('.','varchar(max)')
from #xml.nodes('//root/r') as a(t) )
END
I am Wrting a Stored Function As below in db2.
CREATE OR replace FUNCTION moc_enddate( IN v_date VARCHAR(6),
IN v_message VARCHAR(20)) returns DATE
BEGIN
DECLARE v_temp DATE;
DECLARE v_end_date DATE;
DECLARE v_temp_string VARCHAR(8) DEFAULT '01';
SET v_temp_string = v_temp_string
|| v_date;
SET v_temp = to_date(v_temp_string,'DDMMYYYY');
SET v_end_date = (v_temp + 19 days);
RETURN v_end_date;
EXCEPTION
WHEN no_data_found THEN
SET v_message = 'SqlDataException';
WHEN OTHERS THEN
SET v_message = 'OTHER';
END;
But I am getting the following Exception.
ERROR [42601] [IBM][DB2/AIX64] SQL0104N An unexpected token "EXCEPTION" was found following "RN V_END_MOC_DATE; ". Expected tokens may include.
"<psm_case>".
Maybe, you are using DB2 SQL PL instead of PL/SQL. There is a difference between these languages. If it's the case, the following condition should work:
create or replace procedure CreatePlants
begin
declare sqlstate char(5) default '00000';
declare ErrorMsg varchar(96);
declare exit handler for sqlexception
begin
set ErrorMsg = 'SQLSTATE=' concat sqlstate;
signal sqlstate '99001'
set message_text = ErrorMsg;
end;
create table plants
( ID dec(3), Location varchar(16),
primary key (ID));
label on table plants is 'Plant master';
insert into plants values
( 1, 'Lost Angeles'),
( 2, 'New Yolk'),
( 3, 'Last Vegas');
end
For more references see:
Error Handling in SQL PL, Part 1
Determine The State Of The Error