We have set up a merge replication in SQL Server. One of our biggest deadlocks is this stored procedure up above that is run by subscribers.
CREATE PROCEDURE sys.sp_MSmakegeneration
#gencheck int = 0,
#commongen bigint = NULL,
#commongenguid uniqueidentifier = NULL,
#commongenvalid int = NULL OUTPUT,
#compatlevel int = 90
AS
SET NOCOUNT ON
DECLARE #gen bigint
, #replnick binary(6)
, #dt datetime
, #art_nick int
, #first_ts int
, #makenewrow bit
, #retcode smallint
, #nickbin varbinary(255)
, #maxgendiff_fornewrow bigint
, #count_of_articles int
, #lock_acquired bit
, #lock_resource nvarchar(255)
, #procfailed bit
, #delete_old_genhistory bit
, #close_old_genhistory bit
, #changecount int
, #dbname nvarchar(258)
, #processing_order int
, #prev_processing_order int
, #prev_art_nick int
, #force_leveling bit
, #gen_change_threshold int
declare #cmd nvarchar(4000)
declare #old_bi_gen bigint
declare #bi_view_objid int
--declare #GENSTATUS_OPEN tinyint
--declare #GENSTATUS_MERGE_INSERTED_OPEN tinyint
--declare #GENSTATUS_LOCAL_CLOSED tinyint
--declare #GENSTATUS_TEMPORARILY_CLOSED tinyint
What does this stored procedure exactly do here?
And why should it be repeatedly called while it exists there?
Related
I'm facing issue When I calling this procedure from my main procedure. Error: Cursorfetch: The number of variables declared in the INTO list must match that of selected columns.
ALTER PROCEDURE [ABC].[SKIPPED_EMAILS] (#BatchID INT, #Record VARCHAR(20), #SkippedReason VARCHAR(100), #RecordID INT, #TaskID INT, #TableID INT, #EmailCount INT OUTPUT) AS
BEGIN
DECLARE #EmailBody VARCHAR(4000)
DECLARE #Subject VARCHAR(30)
DECLARE #PersonObj INT
DECLARE #PersonID VARCHAR(10)
DECLARE #PersonName VARCHAR(40)
DECLARE #EmailAddr VARCHAR(50)
DECLARE #PhoneNo VARCHAR(20)
DECLARE #EmailStatus VARCHAR(1) = 'H'
SET #Subject = 'Skipped Emails'
SELECT #EmailBody = Text FROM FLT.EMAIL_TEMP WHERE InformationID = 'SKIPPED_EMAIL'
SELECT #EmailBody = replace(replace(#EmailBody, '[Reason]', #SkippedReason), '[Record]', #Record);
SET #EmailCount = 0;
DECLARE EMAILREC CURSOR LOCAL FOR
SELECT person.PersonObj, person.PersonID, person.PersonName, person.EmailAddr, person.PhoneNo
FROM [ABC].[PERSON] person
LEFT JOIN [ABC].[School] school ON (person.PersonObj = school.StudentObj)
LEFT JOIN [ABC].[Class] class ON (school.StudentObj = class.StudentObj)
WHERE person.Status = 'A'
AND school.StudentType = 'STU'
AND class.AttendeeID= 'ATTENDEE'
AND class.Status = 'A'
OPEN EMAILREC
FETCH NEXT FROM EMAILREC INTO #PersonObj, #PersonID, #PersonName, #EmailAddr, #PhoneNo
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO FLT.LOG_EMAILOG VALUES(0, #BatchID, 0, #TaskID, #TableID, #RecordID, GETDATE(), 'MBX', #Subject, #EmailBody,NULL,'',1, 'PER',#PersonObj, #PersonID, #PersonName, #EmailAddr, #PhoneNo, 'N', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #EmailStatus);
SET #EmailCount = #EmailCount + 1;
FETCH NEXT FROM EMAILREC INTO #PersonObj, #PersonID, #PersonName, #EmailAddr, #PhoneNo
END
CLOSE EMAILREC
DEALLOCATE EMAILREC
END
GO
This does not need to be a cursor at all. Just use INSERT...SELECT...
First rule of cursors in SQL: Don't use them unless you have no other option. SQL likes things to be set-based, do batches as one command, not WHILE loops and cursors.
ALTER PROCEDURE [ABC].[SKIPPED_EMAILS]
(#BatchID INT, #Record VARCHAR(20), #SkippedReason VARCHAR(100), #RecordID INT,
#TaskID INT, #TableID INT, #EmailCount INT OUTPUT)
AS
DECLARE #EmailBody VARCHAR(4000);
SELECT #EmailBody = Text FROM FLT.EMAIL_TEMP WHERE InformationID = 'SKIPPED_EMAIL';
SET #EmailBody = replace(replace(#EmailBody, '[Reason]', #SkippedReason), '[Record]', #Record);
INSERT INTO FLT.LOG_EMAILOG
SELECT
0, #BatchID, 0, #TaskID, #TableID, #RecordID, GETDATE(), 'MBX', 'Skipped Emails', #EmailBody,
NULL,'',1, 'PER',p.PersonObj, p.PersonID, p.PersonName, p.EmailAddr, p.PhoneNo, 'N',
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'H'
FROM [ABC].[PERSON] person p
LEFT JOIN [ABC].[School] school ON (person.PersonObj = school.StudentObj)
LEFT JOIN [ABC].[Class] class ON (school.StudentObj = class.StudentObj)
WHERE person.Status = 'A'
AND school.StudentType = 'STU'
AND class.AttendeeID= 'ATTENDEE'
AND class.Status = 'A';
SET #EmailCount = ##ROWCOUNT;
GO
I strongly suggest you declare the exact column names you are inserting into.
I don't know the structure of FLT.LOG_EMAILOG but I would suggest that you specify the columns of this table in your insert statement like this:
INSERT INTO FLT.LOG_EMAILOG (f1,f2...,f30) VALUES(0, #BatchID, 0, #TaskID, #TableID, #RecordID, GETDATE(), 'MBX', #Subject, #EmailBody,NULL,'',1, 'PER',#PersonObj, #PersonID, #PersonName, #EmailAddr, #PhoneNo, 'N', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #EmailStatus);
I have the following temp tables
CREATE TABLE #Test2ABCD
( VenueID int NOT NULL
, VenueName nvarchar(max)
, VenueAdd nvarchar(max)
, VenueCity nvarchar(max)
, VenueState nvarchar(max)
, VenueCounty nvarchar(max)
, VenueZip nvarchar(max)
, VenuePhone nvarchar(max)
, VenueFax nvarchar(max)
, VenueContactName nvarchar(max)
, VenueContactEmail nvarchar(max)
, VenueContactPhone nvarchar(max)
, VenueWebsite nvarchar(max)
, VenueLat float
, VenueLong float
, VenueRating nvarchar(max)
, MapURL nvarchar(max)
, XMLResult xml);
and
CREATE TABLE #SprocRes2ABCD
( RowID int identity(1,1) not null
, GPSLatitude float
, GPSLongitude float
, City nvarchar(max)
, State nvarchar(max)
, PostalCode nvarchar(max)
, Address nvarchar(max)
, County nvarchar(max)
, MapURL nvarchar(max)
, XMLResults xml);
When I try to execute the following merge statement
MERGE INTO #Test2ABCD t
USING #SprocRes s ON (t.VenueID=s.RowID)
WHEN MATCHED THEN
UPDATE SET t.VenueCounty = s.County
, t.VenueLat = s.GPSLatitude
, t.VenueLong = s.GPSLongitude;
I get the following error:
Msg 207, Level 16, State 1, Line 18
Invalid column name 'RowID'.
I know this has something to do with the "RowId" Column being an identity column but does anyone know how to fix this?
OK so it seems that my eyes have stopped functioning! It was indeed a typo in the final line. Thank you very much for the code review
Code:
Declare #ParmDefinition Nvarchar(1000),
#St Nvarchar(500),
#TTable varchar(30)
Set #TTable='[0Detail]'
Declare #TTempStore Table (
Iden Int,
Row_ Int,
Accs_iden int,
Am_Bed Money,
Am_Bes Money,
Doc_No Decimal(15,0),
Desc_ Nvarchar(500),
Checked bit,
Error_ int)
SET #ParmDefinition = N'#alaki table(Iden Int,
Row_ Int,
Accs_iden int,
Am_Bed Money,
Am_Bes Money,
Doc_No Decimal(15,0),
Desc_ Nvarchar(500),Checked bit,Error_ int) OUTPUT '
Set #St = N' Select * into #alaki from '+#TTable
EXECUTE sp_executesql #St, #ParmDefinition, #alaki = #TTempStore
SELECT * FROM #TTempStore
Errors:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'table'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '#alaki'.
You should post a minimal working sample for us to be able to help you, remember that next time.
Why not declare the table with #TTempStore ?
Declare #St Nvarchar(500),#TTable varchar(30)
Set #TTable='[0Detail]'
create table #TTempStore (
Iden Int,
Row_ Int,
Accs_iden int,
Am_Bed Money,
Am_Bes Money,
Doc_No Decimal(15,0),
Desc_ Nvarchar(500),
Checked bit,
Error_ int)
Set #St=N' Select * into #TTempStore from '+#TTable
EXECUTE #St
Select * from #TTempStore
drop table #TTempStore --here you can leave the table if you have more things to do
I haven't tested it, but it should point you in the right direction. If you need I can probably make a sql fiddle later.
Could the #TTable value be different every time? If it's always going to be [0Detail] then you don't need dynamic SQL. However, here is a dynamic SQL solution to your problem:
Declare #St Nvarchar(500),#TTable varchar(30)
Set #TTable='[0Detail]'
Declare #TTempStore Table (
Iden Int,
Row_ Int,
Accs_iden int,
Am_Bed Money,
Am_Bes Money,
Doc_No Decimal(15,0),
Desc_ Nvarchar(500),
Checked bit,
Error_ int)
Set #St=N' Select * from '+#TTable
INSERT INTO #TTempStore
EXECUTE (#St)
Select * from #TTempStore
I created a table with a stored procedure and I'm trying to insert data into it, but I'm getting this error
Msg 137, Level 15, State 2, Line 49
Must declare the scalar variable "#EmployeeID")
Please help!
Create Table Humanresource.Employee
(
EmployeeID char(3) constraint pkemployeeid primary key,
FirstName varchar(20) not null,
LastName varchar(20) not null,
Emp_Address varchar(30) not null,
Title char(30) constraint ckTitle check(Title in ('Executive','Senior Executive','Management Trainee','Event Manager','Senior Event Manager')),
Phone varchar(20) check(Phone like '[0-9][0-9]-[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9]')
)
Stored procedure:
create procedure Auto_EmpID
#FirstName varchar(20),
#LastName varchar(20),
#Address varchar(30),
#Title varchar(30),
#Phone varchar(20)
AS
Declare #EmployeeID char(3)
if exists (select EmployeeID From HumanResource.Employee Where EmployeeID = 'E101')
BEGIN
Select
#EmployeeID = Max(right(EmployeeID, 2))
from HumanResource.Employee
Select
#EmployeeID = CASE
When #EmployeeID >= 0 AND #Employeeid < 9
Then 'E0' + convert(char(3), #EmployeeID + 1)
When #EmployeeID >= 9 AND #EmployeeID < 99
Then 'E' + convert(char(3), #EmployeeID + 1)
END
END
Else
set #Employeeid = 'E101'
insert into HumanResource.Employee
Values(#EmployeeID, #FirstName, #LastName, #Address, #Title, #Phone)
Return
Exec Auto_EmpID 'Bamidele','Ajose','Lagos','11-1111-111-111'
exec Auto_Empid 'Kunle','Awele','Ikeja','22-3332-655-897'
exec auto_empid 'John','George','Benin','33-5555-7654-443'
select * from humanresource.employee
insert into humanresource.employee(#EmployeeID, #FirstName, #LastName, #Address, #Title, #Phone)
values(#EmployeeID = 'e101', 'Baley', 'Carles', 'Los Angeles', '23-3445-434-344')
These 2 lines have a lot of problems:
insert into humanresource.employee(#EmployeeID,#FirstName,#LastName,#Address,#Title,#Phone)
values(#EmployeeID='e101','Baley','Carles','Los Angeles','23-3445-434-344')
You don't need to prefix the # symbol to column names. That should only be used with variables.
The column list contains 6 columns, but you are only supplying 5 values in the values clause. Please add the 6th value or remove the column where you don't want to insert.
If you want to use the value 'e101', you can directly insert that. If you want to use the variable #employeeID, just pass that. The assignment #employeeID = 'e101' is wrong inside the values clause. You could just do set #employeeID = 'e101 to assign the value before the insert statement.
#employeeID is declared as char(3), so even if you wanted to assign the value 'e101' to it before the insert statement, the value would get truncated to 'e10'. So, you must declare it as char(4) at least.
Another thing is that your stored procedure takes 5 input parameters, but you pass only 4 when calling it. If you want to pass only some parameters instead of all, you need to specify default values for each parameter while creating the procedure, something like this:
create procedure Auto_EmpID
#FirstName varchar(20) = 'somefirstname',
#LastName varchar(20) = 'somelastname',
#Address varchar(30) = 'somecity',
#Title varchar(30) = 'sometitle',
#Phone varchar(20) = '111-111-111'
ALTER PROCEDURE EditEmployee (
#RefNo integer ,
#EmpId nvarchar ,
#Name ntext ,
#Designation ntext ,
#Qualification ntext ,
#Gender ntext ,
#DOB date ,
#Address text ,
#Email ntext ,
#Phone decimal )
as
begin
UPDATE Emp_Sample
SET RefNo=#RefNo,Name=#Name,Designation=#Designation,
Qualification=#Qualification,Gender=#Gender,
DOB=#DOB,Address=#Address,Email=#Email,
Phone=#Phone
where EmpId=#EmpId
END
You need to include #EmpId nvarchar size .
ALTER PROCEDURE EditEmployee (
#RefNo integer ,
#EmpId nvarchar(30) ,
nvarchar [ ( n | max ) ]
When n is not specified in a data definition or variable declaration statement, the default length is 1. When n is not specified with the CAST function, the default length is 30.
HERE
I think you have Cast Problem
Try like this
WHERE EmpId = CAST(#EmpId AS INT)