I am new to stored procedure and managed to google, to create a stored procedure for inserting or updating the database. The set of records are selected from the Oracle Database and depending on the em_id it hase to be iserted or updated in to the Sql Database table using BizTalk
Trying to create a stored procedure to insert or update records depending on a field.
CREATE PROCEDURE [dbo].[usp_InsertorUpdateDB]
#dp_id char(32),
#dv_id char(32),
#em_number char(12),
#email varchar(50),
#emergency_relation char(32),
#option1 char(16),
#status char(20),
#em_id char(35),
#em_title varchar(64),
#date_hired datetime
AS
MERGE [dbo].[em] AS [Target]
USING (SELECT #dp_id, #dv_id , #em_number, #email, #emergency_relation, #option1, #status, #em_id, #em_title, #date_hired)
AS [Source] ([dp_id], [dv_id], [em_number], [email], [emergency_relation], [option1], [status], [em_id], [em_title], [date_hired])
ON [Target].[em_id] = [Source].[em_id]
WHEN MATCHED THEN
UPDATE SET [dp_id] = [Source].[dp_id],
[dv_id] = [Source].[dv_id],
[em_number] = [Source].[em_number],
[email] = [Source].[email],
[emergency_relation] = [Source].[emergency_relation],
[option1] = [Source].[option1],
[status] = [Source].[status],
[em_id] = [Source].[em_id],
[em_title] = [Source].[em_title],
[date_hired] = [Source].[date_hired]
WHEN NOT MATCHED THEN
INSERT ([dp_id], [dv_id], [em_number], [email], [emergency_relation], [option1], [status], [em_id], [em_title],[date_hired])
VALUES ([Source].[dp_id], [Source].[dv_id], [Source].[em_number], [Source].[email], [Source].[emergency_relation], [Source].[option1], [Source].[status], [Source].[em_id], [Source].[em_title], [Source].[date_hired]);
GO
I asked a question two days before because it was showing
Incorrect syntax near the keyword 'WHEN'.
There was a comment showing the code is prone deadlock. Since I am new to Stored Procedures I dont know how to create a stored procedure for insert or update without deadlocks.I am really stuck.
Merge is the reason for deadlock, you can simply try that
CREATE PROCEDURE [dbo].[usp_InsertorUpdateDB]
#dp_id char(32),
#dv_id char(32),
#em_number char(12),
#email varchar(50),
#emergency_relation char(32),
#option1 char(16),
#status char(20),
#em_id char(35),
#em_title varchar(64),
#date_hired datetime
AS
IF ( (SELECT COUNT(em_id) FROM [dbo].[em] WHERE em_id = #em_id) > 0)
UPDATE [dbo].[em]
SET
[dp_id] = #dp_id,
[dv_id] = #dv_id,
[em_number] = #em_number,
[email] = #email,
[emergency_relation] = #emergency_relation,
[option1] = #option1,
[status] = #status,
[em_id] = #em_id,
[em_title] = #em_title,
[date_hired] = #date_hired
WHERE em_id = #em_id
ELSE
INSERT INTO [dbo].[em] (dp_id, dv_id, em_number, email, emergency_relation, option1, [status], em_id, em_title,date_hired)
VALUES (#dp_id, #dv_id, #em_number, #email, #emergency_relation, #option1, #status, #em_id, #em_title, #date_hired);
GO
Related
I'm trying to create a view which dynamically generates text from input parameters. But executing dynamic sql or stored procedure is not allowed in functions. Is there a work around for this?
I'm working on SQL Server 2014
Windows 10
Below is sample script for:
Create tables
Emp_info holds the details of the employee.
Table_list holds the details of the tables with column table_template_id.
table_template_id holds the format of the data to be displayed in the view. This can be customized.
Create function
Accepts 2 input parameters (table_key and emp_key to get the formatted table_template_id)
Create view
Expected output
----------------1. TABLES-------------------------
IF OBJECT_ID('dbo.emp_info', 'U') IS NOT NULL
DROP TABLE dbo.emp_info;
CREATE TABLE emp_info (emp_key INT, table_key INT, emp_fname NVARCHAR(100), emp_lname NVARCHAR(100), city_name NVARCHAR(100), city_zip BIGINT)
INSERT INTO emp_info (emp_key, table_key, emp_fname, emp_lname, city_name, city_zip) VALUES (1, 3, 'Brad', 'Pitt', 'San Jose', 95670)
INSERT INTO emp_info (emp_key, table_key, emp_fname, emp_lname, city_name, city_zip) VALUES (2, 3, 'Will', 'Smith', 'Kansas', 65870)
IF OBJECT_ID('dbo.table_list', 'U') IS NOT NULL
DROP TABLE dbo.table_list;
CREATE TABLE table_list (table_key int, table_name NVARCHAR(100), table_template_id NVARCHAR(100))
INSERT INTO table_list (table_key, table_name, table_template_id) VALUES (3, 'emp_info', '[emp_lname],[emp_fname]-[empkey]')
----------------TABLES-------------------------
----------------2. FUNCTION-------------------------
IF OBJECT_ID(N'crt_emp_temp_id', N'FN') IS NOT NULL
DROP FUNCTION crt_emp_temp_id
GO
CREATE FUNCTION crt_emp_temp_id (#table_key INT, #emp_key INT)
RETURNS NVARCHAR(1000)
AS
BEGIN
DECLARE #mi_table_id_tmp TABLE (
table_key BIGINT,
table_fld NVARCHAR(100),
fld_order BIGINT
)
DECLARE #table_template_id NVARCHAR(100), #table_fld NVARCHAR(100), #table_flds NVARCHAR(100),
#count INT = 0, #max_fld_order INT, #table_name NVARCHAR(100),
#fld_order INT, #sql_stmt NVARCHAR(MAX), #out_value NVARCHAR(1000)
SELECT #table_template_id = table_template_id
,#table_name = table_name
FROM table_list
WHERE table_key = #table_key
SET #table_flds = #table_template_id
WHILE (LEN(#table_flds) > 0)
BEGIN
SET #table_fld = SUBSTRING(#table_flds, CHARINDEX('[', #table_flds)+1, CHARINDEX(']', #table_flds)-2)
SET #table_flds = SUBSTRING(#table_flds, CHARINDEX(#table_fld, #table_flds)+LEN(#table_fld)+1, LEN(#table_flds));
SET #table_flds = SUBSTRING(#table_flds, CHARINDEX('[', #table_flds ), LEN(#table_flds))
SET #count = #count + 1;
INSERT INTO #mi_table_id_tmp (table_key, table_fld, fld_order) VALUES (#table_key, #table_fld, #count);
END
SELECT #max_fld_order = MAX(fld_order) FROM #mi_table_id_tmp
SET #count = 1
WHILE (#count <= #max_fld_order)
BEGIN
SELECT top(1) #table_fld = table_fld
FROM #mi_table_id_tmp
WHERE fld_order = #count
IF (#count = 1)
SET #table_template_id = REPLACE(#table_template_id, '['+#table_fld+']', #table_fld+'+''')
ELSE IF (#count = #max_fld_order)
SET #table_template_id = REPLACE(#table_template_id, '['+#table_fld+']', '''+'+#table_fld);
ELSE
SET #table_template_id = REPLACE(#table_template_id, '['+#table_fld+']', '''+'+#table_fld+'+''');
SET #count = #count + 1
END
SET #sql_stmt = 'select #out = '+#table_template_id+' from '+#table_name+' where emp_key = #e_k'
------------This is where I'm stuck-------------------
EXECUTE sp_executesql #sql_stmt, N'#e_k int,#out NVARCHAR(1000) OUTPUT', #e_k = #emp_key, #out = #out_value OUTPUT
RETURN #out_value
------------This is where I'm stuck-------------------
END
GO
----------------FUNCTION-------------------------
----------------3. VIEW-------------------------
IF object_id(N'emp_info_vw', N'V') IS NOT NULL
DROP FUNCTION emp_info_vw
GO
CREATE VIEW emp_info_vw AS
SELECT crt_emp_temp_id (table_key, emp_key) emp_id,
city_name,
city_zip
FROM emp_info
GO
----------------VIEW-------------------------
--------------4. Expected Output----------------
/*
I'd like to have my output of the view as below
Pitt,Brad-1 San Jose 95670
Smith,Will-2 Kansas 65870
*/
--------------Expected Output----------------
I understand that this error comes when we try to insert characters more than the capacity of column.
But what I am not able to understand is a recent output in which I was getting the error when updating in the table but not when a new record was getting inserted in the table with the same parameter size.
Table structrue:
Entity
(
#EntityID int,
#Name varchar(200),
#FullName varchar(50),
#ParentEntityID int,
#ShortDesc varchar(255),
#LongDesc varchar(2000)
)
When I am trying to insert a new row, it simply truncates the parameter who has value more than its size (here #FullName), but when I try to update the same values on an existing record, it simply throws the exception.
Why can't it just truncate here also?
Edit::
Procedure for update.
ALTER PROCEDURE [dbo].[Entity_Update]
#EntityID int,
#Name varchar(200),
#FullName varchar(410),
#ParentEntityID int,
#ShortDesc varchar(255),
#LongDesc varchar(2000)
AS
set nocount on;
update dbo.Entity set
Name = #Name,
FullName = #FullName,
ParentEntityID = #ParentEntityID,
ShortDesc = #ShortDesc,
LongDesc = #LongDesc,
DateUpdated = GETUTCDATE()
where EntityID = #EntityID;
return 0;
INSERT Procedure is :
ALTER PROCEDURE [dbo].[Entity_Insert]
#Name varchar(200),
#FullName varchar(410),
#ParentEntityID int,
#ShortDesc varchar(255),
#LongDesc varchar(2000),
#UserID int,
#EntityID int OUTPUT
AS
set nocount on;
set xact_abort on;
begin tran
insert dbo.Entity (
Name,
FullName,
ParentEntityID,
ShortDesc,
LongDesc,
RecordStatus,
DateUpdated)
values (#Name,
#FullName,
#ParentEntityID,
#ShortDesc,
#LongDesc,
1,
GETUTCDATE());
select #EntityID = SCOPE_IDENTITY();
CREATE TABLE Entity
(
EntityID INT IDENTITY
NOT NULL
PRIMARY KEY ,
Name VARCHAR(200) ,
FullName VARCHAR(50) ,
ParentEntityID INT ,
ShortDesc VARCHAR(255) ,
LongDesc VARCHAR(2000)
);
INSERT [Entity] ( [Name], [FullName], [ParentEntityID], [ShortDesc],
[LongDesc] )
VALUES ( 'Name', 'FullName', 0, 'Short', 'Long' );
UPDATE [Entity]
SET [LongDesc] = 'Here is an updated value'
WHERE [FullName] = 'FullName';
SELECT *
FROM [Entity] AS [e];
UPDATE [Entity]
SET [LongDesc] = LEFT('Yet another update ' + REPLICATE('blah ', 1000),
2000)
WHERE [FullName] = 'FullName';
SELECT *
FROM [Entity] AS [e];
Works perfectly well for me.
Trying to create a stored procedure to insert or update records depending on a field.
CREATE PROCEDURE [dbo].[usp_InsertorUpdateDB]
#dp_id char(32),
#dv_id char(32),
#em_number char(12),
#email varchar(50),
#emergency_relation char(32),
#option1 char(16),
#status char(20),
#em_id char(35),
#em_title varchar(64),
#date_hired datetime
AS
MERGE [dbo].[em] AS [Target]
USING (SELECT #dp_id, #dv_id , #em_number, #email, #emergency_relation, #option1, #status, #em_id, #em_title, #date_hired)
AS [Source] ([dp_id], [dv_id], [em_number], [email], [emergency_relation], [option1], [status], [em_id], [em_title], [date_hired])
ON [Target].[em_id] = [Source].[em_id]
WHEN MATCHED THEN
UPDATE SET [dp_id] = [Source].[dp_id],
[dv_id] = [Source].[dv_id],
[em_number] = [Source].[em_number],
[email] = [Source].[email],
[emergency_relation] = [Source].[email],
[option1] = [Source].[option1],
[status] = [Source].[status],
[em_id] = [Source].[em_id],
[em_title] = [Source].[em_title],
[date_hired] = [Source].[date_hired],
WHEN NOT MATCHED THEN
INSERT ([dp_id], [dv_id], [em_number], [email], [emergency_relation], [option1], [status], [em_id], [em_title],[date_hired])
VALUES ([Source].[dp_id], [Source].[dv_id], [Source].[em_number], [Source].[email], [Source].[emergency_relation], [Source].[option1], [Source].[status], [Source].[em_id], [Source].[em_title], [Source].[date_hired]);
GO
I am getting error on the line WHEN NOT MATCHED THEN
Incorrect syntax near the keyword 'WHEN'.
I am new to stored procedure and tried to figure it out but couldn't.
You don't want this comma -
UPDATE SET [dp_id] = [Source].[dp_id],
[dv_id] = [Source].[dv_id],
[em_number] = [Source].[em_number],
[email] = [Source].[email],
[emergency_relation] = [Source].[email],
[option1] = [Source].[option1],
[status] = [Source].[status],
[em_id] = [Source].[em_id],
[em_title] = [Source].[em_title],
[date_hired] = [Source].[date_hired]**,**
after [date_hired],
I have created a trigger for a asset_verification. Whenever a new record is inserted in this table, the same record is inserted in the asset_verification_history table because of this trigger.
The trigger is as follows
Create trigger [dbo].[tr_insert_after_asset_verification] on [dbo].[asset_verification]
for insert
As
Begin
declare #verification_id int
declare #id int
declare #audit_id int
declare #date date
declare #status varchar(15)
declare #remarks varchar(200)
declare #creationDate datetime
declare #modificationDate datetime
declare #updatedBy int
declare #audit_action varchar(20)
Select #verification_id = i.verification_id from inserted i
If #verification_id IS NOT NULL
Begin
Select #id = i.id from inserted i
Select #audit_id = i.audit_id from inserted i
Select #date = i.date from inserted i
Select #status = i.status from inserted i
Select #remarks = i.remarks from inserted i
Select #creationDate = i.creationDate from inserted i
Select #modificationDate = i.modificationDate from inserted i
Select #updatedBy = i.updatedBy from inserted i
set #audit_action = 'Insert Record'
INSERT INTO [dbo].[asset_verification_history]
([verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action])
VALUES
(#verification_id
,#id
,#audit_id
,#date
,#status
,#remarks
,#creationDate
,#modificationDate
,#updatedBy
,#audit_action)
End
End
When I insert the data in the asset_verification table using a procedure in which OPEN XML is used, then this trigger works only for the first record. For the rest of the records the trigger doesn't work
The procedure is as follows
Create procedure [dbo].[usp_AddVerificationBulkData]
(
#vXML XML
)
As
Begin
DECLARE #DocHandle INT
SET NOCOUNT ON
EXEC sp_xml_preparedocument #DocHandle OUTPUT, #vXML
Update asset_verification
set
audit_id = x.AuditId,
id = x.SerialId,
date = x.VerificationDate,
status = x.Status
,remarks = x.Remarks
,creationDate = x.CreatedOn
,modificationDate = x.ModifiedOn
,updatedBy = x.ModifiedBy
From
asset_verification a
Inner Join
OpenXml(#DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
On a.audit_id = x.AuditId where a.id = x.SerialId;
INSERT INTO [dbo].[asset_verification]
([id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy])
select SerialId,AuditId,VerificationDate,Status,Remarks,CreatedOn,ModifiedOn,ModifiedBy from OpenXml(#DocHandle,'/ArrayOfAssetVerificationModel/AssetVerificationModel',2)
With(SerialId int, AuditId int, VerificationDate datetime, Status int, Remarks varchar(200), CreatedOn datetime, ModifiedOn datetime, ModifiedBy int) x
where SerialId NOT IN (select a.id from asset_verification a where a.audit_id = x.AuditId);
End
Problem:- How to make this trigger work for every record that is inserted through Open XML ?
You've made the classic mistake of thinking that triggers fire once-per-row. They dont, it's once-per-action, so the inserted pseudo table holds all the rows affected by the action. Your trigger needs to work in a set based manner, not row based. Try this;
CREATE TRIGGER [dbo].[tr_insert_after_asset_verification] ON [dbo].[asset_verification] FOR INSERT AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[asset_verification_history]
( [verification_id]
,[id]
,[audit_id]
,[date]
,[status]
,[remarks]
,[creationDate]
,[modificationDate]
,[updatedBy]
,[audit_action]
)
SELECT i.verification_id
,i.id
,i.audit_id
,i.date
,i.status
,i.remarks
,i.creationDate
,i.modificationDate
,i.updatedBy
,'Insert Record'
FROM inserted i
WHERE i.verification_id IS NOT NULL
END
As an aside, and strictly speaking, your original trigger will log one row, not necessarily the first.
Code:
ALTER PROCEDURE [dbo].[SP_LMS_dealerorusercreation_IUDS]
#dealrid bigint,
#rid bigint,
#stateid bigint,
#regonid bigint,
#Locid bigint,
#pid varchar(MAX),
#address varchar(max),
#dealrname varchar(25),
#landno bigint,
#mobno bigint,
#altcontno bigint,
#email varchar(35),
#desig varchar(25),
#reporting varchar(30),
#status int,
#action varchar(10),
#CompanyId Uniqueidentifier
AS
DECLARE #TranStatus VARCHAR(5)
BEGIN TRY
BEGIN TRANSACTION
IF(#action='Insert')
BEGIN
INSERT INTO LMS_dealerorusercreation(
rid,
stateid,
regonid,
Locid,
addres,
dealrname,
landno,
mobno,
altcontno,
email,
desig,
reporting,
status,
CompanyId
)
VALUES(
#rid,
#stateid,
#regonid,
#Locid,
#address,
#dealrname,
#landno,
#mobno,
#altcontno,
#email,
#desig,
#reporting,
#status,
#CompanyId
)
SELECT #dealrid = dealrid FROM LMS_dealerorusercreation WHERE mobno = #mobno AND email = #email
EXEC [dbo].[SP_LMS_SetDealerProductMapping]
#dealerId = #dealrid,
#prodid = #pid
SET #TranStatus='TRUE';
END
IF(#action='Update')
BEGIN
UPDATE LMS_dealerorusercreation set rid= #rid,
stateid=#stateid,
regonid=#regonid,
Locid=#Locid,
addres=#address,
dealrname=#dealrname,
landno=#landno,
mobno=#mobno,
altcontno=#altcontno,
email=#email,
desig=#desig,
reporting=#reporting,
status=#status
WHERE dealrid=#dealrid
SET #TranStatus='TRUE';
END
IF(#action='Delete')
BEGIN
DELETE FROM LMS_dealerorusercreation WHERE dealrid=#dealrid
SET #TranStatus='TRUE';
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
DECLARE #AI VARCHAR(MAX)
DECLARE #EM VARCHAR(MAX);
SET #AI = 'Not Provided'
SET #EM = ERROR_MESSAGE();
EXEC USP_SetException
#ExceptionDetail = #EM,
#AdditionalInfo = #AI
SET #TranStatus='FALSE';
END CATCH
SELECT #TranStatus;
The error am getting is
Cannot insert the value NULL into column 'dealrid', table 'DB_LMS.dbo.LMS_dealerorusercreation'; column does not allow nulls. INSERT fails.
You need to do one of two things, either...
ensure that you pass in a non-null value for the column, or;
ensure that your column accepts a null value if that is a desired property of the field.
Errors I see in the code.
While inserting into the table LMS_dealerorusercreation, you never selected dealrid column. Please select the same.
INSERT INTO LMS_dealerorusercreation(
rid,
stateid,
regonid,
Locid,
addres,
dealrname,
landno,
mobno,
altcontno,
email,
desig,
reporting,
status,
CompanyId,
dealrid
)
VALUES(
#rid,
#stateid,
#regonid,
#Locid,
#address,
#dealrname,
#landno,
#mobno,
#altcontno,
#email,
#desig,
#reporting,
#status,
#CompanyId,
#dealrid
)
it is juat as the error message states.
you are trying to do an insert to a table where dealrid has been created with not null. if you look at your insert statement, you are not selecting and passing a value to it.