I have 3 SQL Objects:
Table Employee with three fields (id, name, salary)
Procedure Insert_employee [to insert in employee table]
Trigger [to make validation for table]
My problem: if call Insert_employee by Entity Framework,
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
ALTER PROC [dbo].[Insert_Employees]
(
#id AS INT,
#name AS NVARCHAR(max),
#salary AS NUMERIC(18,3)
)
AS
BEGIN
DECLARE #error AS NVARCHAR(max)
BEGIN TRANSACTION
INSERT INTO employee(Id, Name,Salary)
SELECT #id, #name , #salary
SELECT #error = ##ERROR
IF #error = 0 COMMIT ELSE ROLLBACK
END
ALTER TRIGGER [dbo].[INS_employee] ON [dbo].[Employee]
INSTEAD OF INSERT
AS
BEGIN
IF EXISTS (SELECT * FROM inserted WHERE inserted.name = '')
BEGIN
RAISERROR('name is empty',16,1);
END
ELSE
INSERT INTO employee(id, Name, Salary)
SELECT id, Name, Salary FROM inserted
END
Related
I have multiple queries in nested for each loop with millions of records its tack long to process queries with each iteration of loop from asp.net MVC then I have create a cursor instead of executing multiple queries from the action but can't retrieve fetched rows in list/variable.
SQL:
ALTER proc [dbo].[sp_get_AllofPostings]
#comp nvarchar(max),
#TNumber int
as
begin
DECLARE #Id NVARCHAR(128), #AccountCode varchar(max), #TrasactionNumber int, #LedgerNumber int, #RefCode varchar(50), #IsDebit bit, #Amount float, #pcomp nvarchar(max), #CreateDate datetime, #status bit
-- declare cursor
DECLARE postings_cursor CURSOR FOR
SELECT * FROM Postings where TrasactionNumber = #TNumber and CoId=#comp and Amount IS NOT NULL
OPEN postings_cursor;
FETCH NEXT FROM postings_cursor INTO #Id, #AccountCode, #TrasactionNumber, #LedgerNumber, #RefCode, #IsDebit, #Amount, #pcomp, #CreateDate, #status
WHILE ##FETCH_STATUS = 0
BEGIN
--do somthing here
Declare #LAccountName nvarchar(max), #LGLAccount int, #GLName nvarchar(max), #Gaccountcode varchar(50)
SET #LAccountName = (select AccountName from Ledgers where CoId=#comp and AccountCode=#AccountCode)
SET #LGLAccount = (select GLAccount from Ledgers where CoId=#comp and AccountCode=#AccountCode)
SET #GLName = (select GLName from GLAccounts where CoId=#comp and Keyid = #LGLAccount)
SET #Gaccountcode = (select Name from Groups where CoId=#comp and Code = #AccountCode)
FETCH NEXT FROM postings_cursor INTO #Id, #AccountCode, #TrasactionNumber, #LedgerNumber, #RefCode, #IsDebit, #Amount, #pcomp, #CreateDate, #status
END;
CLOSE postings_cursor;
DEALLOCATE postings_cursor;
END
C#:
var posting = db.sp_get_AllofPostings(comp, item.Number);
I have a table called Employees.
This table is updated daily with a scheduled job from Active Directory.
We currently have the following stored procedure that checks if a particular employee exists in the Employee table.
If yes, update the rest of the employee records in that table.
If no, then insert the employee record into that Employee table.
In order to determine whether an employee exists in Employee table or not, employees are required to FIRST enter their employeeID. This is not an auto-generated ID. It is imported into the Employee table along with rest of employee records from Active Directory if that employee record exists in Active Directory.
The issue we are having is that we are not able insert a new employee record into Employee table. Neither are we able to update the record.
We kept getting the message that:
Cannot insert the value NULL into column 'employeeID', table 'Employees'; column does not allow nulls. INSERT fails.The statement has been terminated.
I suspect the issue is with my stored procedure but not sure what the issue is.
Any assistance is greatly appreciated.
Here is my stored proc and the code I am using to try to invoke it.
ALTER PROCEDURE [dbo].[usp_Employees]
#FullName varchar(75),
#address varchar(100),
#city varchar(50),
#state varchar(50),
#zip varchar(50),
#eid int = 0 OUTPUT
AS
BEGIN
SET NOCOUNT ON;
begin tran
if exists (select * from Employees where employeeID = #eid)
begin
UPDATE Employees SET [empFullName] = #FullName
,[Address] = #address
,[City] = #city
,[State] = #state
,[Zip] = #zip where employeeID = #eid
end
else
begin
INSERT INTO [dbo].[Employees]
([empFullName]
,[Address]
,[City]
,[State]
,[Zip]
,[employeeID])
VALUES
(#FullName
,#address
,#city
,#state
,#zip
,#eid)
SET #eid = SCOPE_IDENTITY()
end
commit tran
END
int eid = 0;
SqlCommand cmd = new SqlCommand("usp_Employees", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#FullName", txtfname.Text);
cmd.Parameters.AddWithValue("#address", txtfaddress.Text);
cmd.Parameters.AddWithValue("#city", txtcity.Text);
cmd.Parameters.AddWithValue("#state", ddlstates.SelectedValue);
cmd.Parameters.AddWithValue("#zip", txtfzip.Text);
SqlParameter employeeID = cmd.Parameters.Add("#eid", SqlDbType.Int);
employeeID.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
eid = Convert.ToInt32(employeeID.Value);
I need to grab this employeeID after insert or update and insert it in other tables.
I think your issue is simply you are not passing the employee id in as it should be. Pass it in with the rest of the code, and discard the output and SCOPE_IDENTITY. Amend you C# to add it to the stored proc along with the rest and it should be fine. Also, not sure of the point of using BEGIN TRAN and COMMIT TRAN without a try/catch, to either commit, or rollback. Otherwise it is just getting committed with or without:
ALTER PROCEDURE [DBO].[USP_EMPLOYEES]
#FULLNAME VARCHAR(75),
#ADDRESS VARCHAR(100),
#CITY VARCHAR(50),
#STATE VARCHAR(50),
#ZIP VARCHAR(50),
#EMPLOYEEID INT ,
#EID INT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRAN
IF EXISTS (SELECT * FROM EMPLOYEES WHERE EMPLOYEEID = #EID)
BEGIN
UPDATE EMPLOYEES
SET [EMPFULLNAME] = #FULLNAME
,[ADDRESS] = #ADDRESS
,[CITY] = #CITY
,[STATE] = #STATE
,[ZIP] = #ZIP
WHERE EMPLOYEEID = #EID
END
ELSE
BEGIN
INSERT INTO [DBO].[EMPLOYEES]
([EMPFULLNAME]
,[ADDRESS]
,[CITY]
,[STATE]
,[ZIP]
,[EMPLOYEEID])
VALUES
(#FULLNAME
,#ADDRESS
,#CITY
,#STATE
,#ZIP
,#EID)
END
COMMIT TRAN
END
You can use MERGE (starting with Sql Server 2008)
MERGE Employees AS target
USING (SELECT #eid,
#fullName,
#address,
#city,
#state,
#zip) AS source (eid, fullName, address, city, state, zip)
ON (target.employeeID = source.eid)
WHEN MATCHED THEN
UPDATE SET
empFullName = source.fullName,
Address = source.address,
City = source.city,
State = source.state,
Zip = source.zip
WHEN NOT MATCHED THEN
INSERT (employeeID, empFullName, Address, City, State, Zip)
VALUES (source.eid,
source.fullName,
source.address,
source.city,
source.state,
source.zip)
OUTPUT inserted.employeeID; -- return updated or inserted Id
...
#eid int
as
begin
...
SET #eid = SCOPE_IDENTITY()
INSERT INTO [dbo].[Employees]
([empFullName]
,[Address]
,[City]
,[State]
,[Zip]
,[employeeID])
VALUES
(#FullName
,#address
,#city
,#state
,#zip
,#eid)
I have a problem with high frequency inserts. I use a stored procedure to insert data into my table, but I get this error:
System.Data.SqlClient.SqlException (0x80131904): Violation of PRIMARY KEY constraint 'PK_MyTable'. Cannot insert duplicate key in object 'dbo.MyTable'. The duplicate key value is (3001749001, 0, 02/09/2016, abc).
The statement has been terminated.
This is my code:
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SetData]
#Key1 nvarchar(50),
#Key2 int,
#Key3 nvarchar(50),
#Key4 nvarchar(50),
#Data1 nvarchar(100)
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION;
IF EXISTS (SELECT 1
FROM [dbo].[MyTable]
WHERE [Key1] = #Key1 AND [Key2] = #Key2 AND [Key3] = #Key3 AND [Key4] = #Key4)
BEGIN
UPDATE [dbo].[MyTable]
SET [Data1] = #Data1
,[UpdateTime] = getdate()
WHERE [Key1] = #Key1 AND [Key2] = #Key2 AND [Key3] = #Key3 AND [Key4] = #Key4
END
ELSE
BEGIN
INSERT INTO [dbo].[MyTable]
([Key1]
,[Key2]
,[Key3]
,[Key4]
,[Data1]
,[UpdateTime])
VALUES
(#Key1,
#Key2,
#Key3,
#Key4,
#Data1,
getdate())
END
COMMIT TRANSACTION;
I want to generate a sequence number based on the column value. I want to have this kind of output. I gonna use this in c# .net winform as GridView output
TABLE1
ID Name NoStub
1 arte 3
2 gonzake 2
TABLE2
ID Name StubNumberStart StubNumberEnd
1 arte 0001 0003
2 gonzake 0004 0005
Try this query.. it will give result from Table 2 to Table 1
DECLARE #T1 AS TABLE (ID INT, NAME VARCHAR(50), STUBNUMBER VARCHAR(10))
INSERT INTO #T1 VALUES ( 1, 'ARTE', '001')
INSERT INTO #T1 VALUES ( 1, 'ARTE', '002')
INSERT INTO #T1 VALUES ( 1, 'ARTE', '003')
INSERT INTO #T1 VALUES ( 1, 'GONZAKE', '004')
INSERT INTO #T1 VALUES ( 1, 'GONZAKE', '005')
SELECT * FROM #T1
SELECT DISTINCT ID ,NAME, COUNT(*) AS NOSTUB FROM #T1
GROUP BY ID, NAME
If your request is different from Table 1 to Table 2 then please let me know .. you will get new query...
ALTER PROCEDURE ExpandIt
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Id int;
DECLARE #name varchar(50);
DECLARE #noStub int;
DECLARE #stubNumber char(8);
DECLARE #count as int = 0;
DECLARE #continuedID as int = 0;
DECLARE t1 CURSOR FAST_FORWARD FOR
SELECT ID, Name,NoStub from Table1
OPEN t1
FETCH NEXT FROM t1 INTO #Id, #name, #noStub
WHILE ##FETCH_STATUS = 0
BEGIN
WHILE (#count < #noStub)
BEGIN
SET #count = #count + 1;
SET #stubNumber = ('0000' + CONVERT (CHAR, #continuedID + #count));
SET #stubNumber = SUBSTRING (#stubNumber,LEN(#stubNumber)-4+1, 4);
INSERT INTO Table2 (ID, Name, StubNumber)
VALUES (#Id, #name,#stubNumber);
END
SET #continuedID = #count;
SET #count = 0;
FETCH NEXT FROM t1 INTO #Id, #name, #noStub
END
CLOSE t1 ;
DEALLOCATE t1
END
I have two tables.
dbo.Emp
EmpID(PK) | Name | TypeID(FK)
dbo.EmpType
TypeID(PK) | Type
TypeID: AutoIncrement only in dbo.EmpType
When I update value for TypeID in Emptype, it needs get stored in TypeID of dbo.Emp
I used SP which is not working.
Create Procedure bridge_Type(
#EmpID INT,
#Name varchar(50),
#Mob2 numeric(10,0),
#Email varchar(50),
#Type varchar(50)
)
AS
DECLARE #TYPEID int
Set NOCOUNT OFF
BEGIN TRANSACTION
Insert into dbo.Emp VALUES (#EmpID, #Name, #Mob2, #Email, #TYPEID)
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
INSERT INTO dbo.EmpType VALUES (#Type)
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
declare #id int
SET #id= #TYPEID;
Update Dbo.Emp
Set #TYPEID= (Select TypeID from dbo.EmpType
WHERE TypeID=#typeID)
COMMIT
Try This SP, This will first insert the EmpType, and From SCOPE_IDENTITY() it will get the Inserted Identity Value, and then insert emp.
Create Procedure bridge_Type(
#EmpID INT,
#Name varchar(50),
#Mob2 numeric(10,0),
#Email varchar(50),
#Type varchar(50)
)
AS
DECLARE #TYPEID int
Set NOCOUNT OFF
BEGIN TRANSACTION
INSERT INTO dbo.EmpType VALUES (#Type)
SET #TYPEID = SCOPE_IDENTITY()
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
Insert into dbo.Emp VALUES (#EmpID, #Name, #Mob2, #Email, #TYPEID)
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
COMMIT
Not 100% sure why you would be updating the typeID in your EmpType table (particularly as it is an autoincrement key), however, you could look at updating your FK constraint to 'cascade on update':
When to use "ON UPDATE CASCADE"
http://msdn.microsoft.com/en-us/library/aa933119(v=sql.80).aspx