cross database query on sql server 2014 - sql-server-2014

I have a database with a memory optimized table. I want to archive this table in another database. I want to write an stored procedure to do that.
I am implemented below sample from 1 and 2 successfully, but in these sample, the first database is not in memory and the second database is in memory.
In my case, the first database is in memory and the second one can be in memory or not.
Here is my code:
1- my table :
USE [TestReport]
GO
/****** Object: Table [dbo].[Report] Script Date: 1/22/2018 4:40:04 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Report]
(
[ReportID] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[Year] [int] NOT NULL,
[DayOfYear] [int] NOT NULL,
[ProductType] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[ApplicationID] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[TotalSize] [bigint] NOT NULL DEFAULT ((0)),
[TotalCount] [bigint] NOT NULL DEFAULT ((0)),
[LastReportTimeSpan] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NULL,
INDEX [idx] NONCLUSTERED HASH
(
[ReportID],
[DayOfYear]
)WITH ( BUCKET_COUNT = 131072),
CONSTRAINT [pk] PRIMARY KEY NONCLUSTERED HASH
(
[ReportID],
[Year],
[DayOfYear],
[ProductType],
[ApplicationID]
)WITH ( BUCKET_COUNT = 131072)
)WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA )
GO
2- simple Stored procedure
CREATE PROCEDURE [dbo].[ArchiveReport]
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
(
TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english'
)
BEGIN
DECLARE #currentdate DATETIME2;
SET #currentdate = GETDATE();
declare #maintainDay INT = 5
INSERT TestReportArchive.[dbo].Report
SELECT [ReportID],
[Year],
[DayOfYear],
[ProductType],
[ApplicationID],
[TotalSize],
[TotalCount],
[LastReportTimeSpan]
FROM [dbo].[Report]
WHERE DATEADD(day, [DayOfYear] + #maintainDay, DATEADD(YEAR, [Year] - 1900, 0)) > #currentdate;
DELETE FROM [dbo].[Report]
WHERE DATEADD(day, [DayOfYear] + #maintainDay, DATEADD(YEAR, [Year] - 1900, 0)) > #currentdate;
END;
END
3- simple stored procedure error
Msg 4512, Level 16, State 3, Procedure ArchiveReport, Line 12
Cannot schema bind procedure 'dbo.ArchiveReport' because name 'TestReportArchive.dbo.Report' is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.
TestReportArchive is my destination database
4- using 1 and 2. definition of table variable
USE [TestReport]
GO
/****** Object: UserDefinedTableType [dbo].[MemoryType] Script Date: 1/22/2018 4:35:14 PM ******/
CREATE TYPE [dbo].[MemoryType] AS TABLE(
[ReportID] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[Year] [int] NOT NULL,
[DayOfYear] [int] NOT NULL,
[ProductType] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[ApplicationID] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NOT NULL,
[TotalSize] [bigint] NOT NULL,
[TotalCount] [bigint] NOT NULL,
[LastReportTimeSpan] [nvarchar](50) COLLATE Latin1_General_100_BIN2 NULL,
INDEX [idx] NONCLUSTERED HASH
(
[ReportID],
[DayOfYear]
)WITH ( BUCKET_COUNT = 131072)
)
WITH ( MEMORY_OPTIMIZED = ON )
GO
5- stored procedure with table variable
CREATE PROCEDURE [dbo].[ArchiveReport]
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
(
TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english'
)
BEGIN
DECLARE #currentdate DATETIME2;
SET #currentdate = GETDATE();
declare #maintainDay INT = 5
DECLARE #InMem [dbo].[MemoryType];
INSERT #InMem
SELECT [ReportID],
[Year],
[DayOfYear],
[ProductType],
[ApplicationID],
[TotalSize],
[TotalCount],
[LastReportTimeSpan]
FROM [dbo].[Report]
WHERE DATEADD(day, [DayOfYear] + #maintainDay, DATEADD(YEAR, [Year] - 1900, 0)) > #currentdate;
INSERT TestReportArchive.[dbo].[Report]
SELECT [ReportID],
[Year],
[DayOfYear],
[ProductType],
[ApplicationID],
[TotalSize],
[TotalCount],
[LastReportTimeSpan]
FROM #InMem
DELETE FROM [dbo].[Report]
WHERE DATEADD(day, [DayOfYear] + #maintainDay, DATEADD(YEAR, [Year] - 1900, 0)) > #currentdate;
END;
END
6- Error from 5 stored procedure
Msg 4512, Level 16, State 3, Procedure ArchiveReport, Line 25
Cannot schema bind procedure 'dbo.ArchiveReport' because name 'TestReportArchive.dbo.Report' is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.
TestReportArchive is my destination database

Cross-database queries involving Memory-Optimized Tables are not supported.
Unsupported SQL Server Features for In-Memory OLTP
A query cannot access other databases if the query uses either a
memory-optimized table or a natively compiled stored procedure. This
restriction applies to transactions as well as to queries.

Ultimately I created a non-memory-optimized table (ReportTemp) on the testReport (first Database) and change the stored procedure to insert data from Report Table to ReportTemp Table in the first database. Then I write another SP to move Data to archive Database.

Related

Insert auto increment primary key into foreign key table

I have 2 tables User and UserLogin. UserLogin have a foreign key relationship with User table. What I want to do here is whenever I insert data into the User table through my API their autogenerated(user_id) auto-inserted into UserLogin table.
User table:
user_id | user_name | user_email
UserLogin table:
user_id | user_password | user_number
So when I run my query to add name and email in User table then autoincremented user_id is automatically inserted in UserLogin table with the provided password and number. How can I achieve this and is that thread safe?
yes it is possible and usually can be optained by ##identity try something like
set nocount off;
insert into User Values("Name","Email")
declare #lastID = ##identity
insert into UserLogin values(#lastID,"Password","number")
This code helps you
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[User](
[user_id] [int] IDENTITY(1,1) NOT NULL,
[user_name] [varchar](100) NULL,
[user_email] [varchar](100) NULL,
[salt] [uniqueidentifier] NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[user_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[UserLogin](
[UserLoginId] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NULL,
[user_password] [binary](1) NULL,
[user_number] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_UserLogin_User] FOREIGN KEY([user_id])
REFERENCES [dbo].[User] ([user_id])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_UserLogin_User]
GO
CREATE PROC [dbo].[Usp_UserLogin]
(
#user_name VARCHAR(100)
,#user_email VARCHAR(100)
,#user_password VARCHAR(200)
,#user_number INT
)
AS
Begin
SET NOCOUNT ON
DECLARE #Salt UNIQUEIDENTIFIER =NEWID()
,#IdentityNUmber INT
,#responseMessage nvarchar(1000)
BEGIN TRY
INSERT INTO Dbo.[User]([user_name],[user_email],[salt])
SELECT #user_name
,#user_email
,#salt
SET #IdentityNUmber=SCOPE_IDENTITY()
INSERT INTO Dbo.[UserLogin]([user_id],[user_password],user_number)
SELECT
#IdentityNUmber
,#user_number
,HASHBYTES('SHA2_512', #user_password + CAST(#salt AS NVARCHAR(36)))
END TRY
BEGIN CATCH
SET #responseMessage=ERROR_MESSAGE()
END CATCH
END
GO
Execute the Procedure
EXEC [Usp_UserLogin] #user_name='Test1',#user_email='Test1#gmail',#user_password='Test1#123',#user_number=2

Why does ##RowCount shows 1 row effected but SCOPE_IDENTITY() returns NULL?

i have the following stored procedure.
alter proc uspUpdtStudent
#pStudID int,
#pTitle char(10),
#pFName varchar(50),
#pLName varchar(50),
#pDOB date,
#pGender char(1),
#pIsPriorStud bit,
#pCitizen varchar(50),
#pResidency varchar(50),
#pPic varbinary(max),
--#pOldContact as dbo.Contact readonly,
#pNewContact as dbo.Contact readonly,
#pProgTrack tinyint,
#pProgID int,
#pid int output -- why not EnrID?
as
begin
SET NOCOUNT ON;
declare #tblNew as table (rw_id int identity(1,1), addL1 varchar(200), sub varchar(100), town varchar(100), post int)
select #pTitle, #pFName, #pLName, #pDOB, #pGender, #pIsPriorStud, #pCitizen, #pResidency, #pPic, #pStudID
update dbo.Students
set
Title=#pTitle,
FName=#pFName,
LName=#pLName,
DOB=#pDOB,
Gender=#pGender,
IsPriorStud=#pIsPriorStud,
Citizenship=#pCitizen,
Residency=#pResidency,
StudImg=#pPic,
DateOfRago=GETDATE()
where StudID =#pStudID
select #pStudID as 'Passed Student ID'
declare #rowcount int
set #pid = SCOPE_IDENTITY()
--select #pid
set #rowcount = ##ROWCOUNT
select #rowcount as 'Effected Row count'
if #rowcount > 0
begin
SELECT #pid as 'Student table row ID'
end
else
begin
set #pid = -1
--rollback tran
return 302
end
end
go
Then i pass theses values to the stored procedure
USE [SMSV1]
GO
declare #p13 int
set #p13=-1
declare #p14 dbo.Contact
insert into #p14 values(N'fyyyfyf',N'woeoeoo',N'kokokok',N'123456')
exec uspUpdtStudent #pStudID=100000007,#pTitle=N'Mr.',#pFName=N'George',#pLName=N'kadafi',#pDOB='1940-12-12 00:00:00',#pGender=N'M',#pIsPriorStud=0,#pCitizen=N'LIBIYA',#pResidency=N'LIBIYA',#pPic=null,#pProgID=15,#pProgTrack=2,#pid=#p13 output,#pNewContact=#p14
what is funny about is, it adds a row to the student table but when i tried to access the row id from SCOPE_IDENTITY() it shows as NULL. the IF condition executes because ##ROWCOUNT is greater than zero also As you can see in the code i have even saved the id value in a variable #pid. I have attached this video on youtube so it might help to understand understand the situation.
Here is my student table
USE [SMSV1]
GO
/****** Object: Table [dbo].[Students] Script Date: 12/18/2014 07:39:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Students](
[ID] [int] IDENTITY(1,1) NOT NULL,
[StudID] [int] NULL,
[Title] [char](10) NULL,
[FName] [varchar](50) NULL,
[LName] [varchar](50) NULL,
[DOB] [date] NULL,
[Gender] [char](1) NULL,
[IsPriorStud] [bit] NULL,
[Citizenship] [varchar](50) NULL,
[Residency] [varchar](50) NULL,
[StudImg] [varbinary](max) NULL,
[DateOfRago] [datetime] NULL,
[Updt] [datetime] NOT NULL,
[IsActive] [bit] NULL,
CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Students] ADD CONSTRAINT [DF_Students_Updt] DEFAULT (getdate()) FOR [Updt]
GO
thanks
##ROWCOUNT gets reset per each statement. Try the following to see:
DECLARE #Test INT;
SELECT 10 UNION ALL SELECT 20;
SELECT ##ROWCOUNT;
SELECT 10 UNION ALL SELECT 20;
SET #Test = 1;
SELECT ##ROWCOUNT;
Returns:
10
20
2
10
20
1 -- this is 1 instead of 2 due to the SET command being between the second two SELECTs
If you want SET #RowCount = ##ROWCOUNT; to be accurate, it has to be the next statement after the UPDATE. Where you currently have it (i.e. after a SET command) #rowcount will always be 1 no matter what happens with the UPDATE.
Also, there is no INSERT, so SCOPE_IDENTITY() would have to return NULL. And why would you need to dynamically get the ID anyway? Isn't it being passed into the proc via #pStudID? If for some reason the [StudID] field in the [Students] table is not the IDENTITY field, you can still get that via the OUTPUT clause:
UPDATE dbo.Students
SET
Title=#pTitle,
FName=#pFName,
LName=#pLName,
DOB=#pDOB,
Gender=#pGender,
IsPriorStud=#pIsPriorStud,
Citizenship=#pCitizen,
Residency=#pResidency,
StudImg=#pPic,
DateOfRago=GETDATE()
OUTPUT INSERTED.ID -- this is the IDENTITY field as per the CREATE TABLE statement
WHERE StudID = #pStudID;
Using the OUTPUT clause in this manner will result in a 1 row, 1 column result set ONLY IF a row is updated. If there is no matching row, there is no result set. If you want a clearer indication of no row updated than merely no result set, as I mentioned above, put the SET #RowCount = ##ROWCOUNT; just after the UPDATE and then you can test for IF (#RowCount = 0)....
IF you need the ID field in the #pid variable since it is an OUTPUT parameter, then you need to capture the result set of the UPDATE...OUTPUT into a temp table or table variable:
DECLARE #UpdatedID TABLE (ID INT);
UPDATE dbo.Students
SET
Title=#pTitle,
FName=#pFName,
LName=#pLName,
DOB=#pDOB,
Gender=#pGender,
IsPriorStud=#pIsPriorStud,
Citizenship=#pCitizen,
Residency=#pResidency,
StudImg=#pPic,
DateOfRago=GETDATE()
OUTPUT INSERTED.ID -- this is the IDENTITY field as per the CREATE TABLE statement
INTO #UpdatedID (ID)
WHERE StudID = #pStudID;
SELECT #pid = ID
FROM #UpdatedID;
IF (#pid IS NULL)
BEGIN
SET #pid = -1;
RETURN 302;
END;
From SCOPE_IDENTITY (Transact-SQL) (Bold for emphasis mine)
Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You are doing an Update, not an insert, hence it is not being set.

SQL Stored procedure multi insert handle looping or multiple scope_insert values

So it's my understanding that looping and cursors should be avoided unless absolutely necessary. In my situation it seems to me that if I have to rely on them I am doing it wrong so I'd like the communities input.
I am writing a stored procedure to add items to a queue, the number of items added are dependent on the intervals setup for the item type. Once the data is inserted into the queue I need to add the ID's of the queue items to other tables. I am running into an issue here as I generally rely on SCOPE_IDENTITY() to pull the ID for return.
Below is my table structure:
CREATE TABLE QueueItem (
QueueItemID [int] IDENTITY NOT NULL,
ReferenceID [int] NOT NULL,
StartDate [datetime] NOT NULL
);
CREATE TABLE CatalogDate (
ReferenceID [int] NOT NULL,
CatalogID [int] NOT NULL,
DayCount [int] NOT NULL
);
CREATE TABLE ItemInterval (
ReferenceID [int] NOT NULL,
Interval [int] NOT NULL
);
CREATE PROCEDURE SetQueueItem
#ReferenceID [int],
#UserID [int]
AS
BEGIN
DECLARE #DayCount [int]
DECLARE #CatalogID [int]
DECLARE #QueueItemID [int]
SELECT #DayCount = DayCount, #CatalogID = CatalogID
FROM CatalogDate
WHERE ReferenceID = #ReferenceID
DECLARE #Date [datetime] = --SELECT Date from another table using #UserID and #CatalogID
DECLARE #StartDate [datetime] = (SELECT DATEADD(dd, #DayCount, #Date))
INSERT INTO QueueItem(ReferenceID, StartDate)
SELECT #ReferenceID, DATEADD(#DateCount-Interval), #Date)
FROM ItemInterval
WHERE ReferenceID = #ReferenceID --SELECT RETURNS MULTIPLE ROWS
Now once the insert of multiple records has been done I need to take the QueueItemID's that were generated from the inserts and insert them along with some additional data in two other tables.
The only ways I can see of accomplishing this is by either breaking up the INSERT to loop through each record in ItemInterval and insert them one at a time, or to query the MAX records from the QueueItem table before and after the insert and then loop through the difference assuming the ID's are perfectly sequential.
Thoughts?
Take a look at the OUTPUT clause.
http://technet.microsoft.com/en-us/library/ms177564.aspx
http://msdn.microsoft.com/en-us/library/ms177564.aspx
Thanks to #StarShip3000 for the references on OUTPUT
To solve this problem I dumped the results into a variable table using OUTPUT and then use that table to insert the results in the other tables.
DECLARE #QueueItemTable TABLE
(
ItemID [int]
)
INSERT QueueItem(ReferenceID, StartDate)
OUTPUT inserted.QueueItemID INTO #QueueItemTable(ItemID)
SELECT #ReferenceID, DATEADD(#DateCount-Interval), #Date)
FROM ItemInterval
WHERE ReferenceID = #ReferenceID --INSERTS IDENTITIES into #QueueItemTable variable
--Insert into other tables
INSERT QueueRelationship(QueueItemID)
SELECT ItemID
FROM #QueueItemTable
Viola!

SQL Server input trigger to azure trigger

I just transferred one of my pages to a Windows Azure Account. Everything went smooth .. until I tried to create some data. My trigger, which worked fine with MSSQL2008 fails on azure - how could I fix this trigger:
CREATE TRIGGER creator
ON someTable
FOR INSERT
AS
DECLARE #someTableID INT;
SELECT #someTableID=(SELECT someTableID FROM INSERTED)
INSERT INTO Preisgruppe ( Name, someTableID, UserPreisgruppe_ID ) VALUES ( 'Gast', #someTableID, 1)
INSERT INTO Oeffnungszeit ( someTableID, Tag_ID, von,bis) VALUES ( #someTableID, 0, '00:00','00:00'),( #someTableID, 1, '00:00','00:00'),( #someTableID, 2, '00:00','00:00'),( #someTableID, 3, '00:00','00:00'),( #someTableID, 4, '00:00','00:00'),( #someTableID, 5, '00:00','00:00'),( #someTableID, 6, '00:00','00:00')
GO
Nothing is looking bad in this Trigger.
I did try your code and it's working fine.
So it could be the structure. My look like this:
CREATE TABLE [dbo].[someTable](
[someTableID] [int] IDENTITY(1,1) NOT NULL,
[Column1] [nvarchar](50) NOT NULL
)
CREATE TABLE [dbo].[Preisgruppe](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[someTableID] [int] NULL,
[UserPreisgruppe_ID] [int] NULL
)
CREATE TABLE [dbo].[Oeffnungszeit](
[ID] [int] IDENTITY(1,1) NOT NULL,
[someTableID] [int] NOT NULL,
[Tag_ID] [int] NOT NULL,
[von] [time](7) NULL,
[bis] [time](7) NULL
)
Also it could be nice to have the Error message...
Just to provide another example, here is what I use...
TABLE DEFINITION:
This is just a normal table except the "main body" of AUDIT fields are in the HISTORY table.
CREATE TABLE [data].[Categories](
[Id] [uniqueidentifier] NOT NULL DEFAULT (newid()),
[Name] [nvarchar](250) NOT NULL,
[Description] [nvarchar](500) NULL,
[DisplayOrder] [bigint] NULL,
[ProductCount] [bigint] NULL,
[IsActive] [bit] NOT NULL CONSTRAINT [DF_Categories_IsActive] DEFAULT ((1)),
[UpdatedBy] [nvarchar](360) NOT NULL
)
On a side-note...
Heap tables are not allowed, so make each "Id" columns PRIMARY
You should also get used to using GUID's for your PRIMARY KEY's
HISTORY TABLE DEFINITION (used for audit purposes):
This table is used for AUDIT purposes. You still get to see who did what & when, except now, the history isn't buried in your main table and won't slow-down your INDEXES. And...you get TRUE AUDIT beyond that of mere log-shipping.
CREATE TABLE [history].[data_Categories](
[Id] [uniqueidentifier] NOT NULL DEFAULT (newid()),
[EntityId] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[Description] [nvarchar](500) NULL,
[ProductCount] [bigint] NULL,
[DisplayOrder] [bigint] NULL,
[IsActive] [bit] NOT NULL,
[UpdatedBy] [nvarchar](360) NOT NULL,
[UpdateType] [nvarchar](50) NOT NULL,
[UpdatedDate] [datetime] NOT NULL
)
GO
ALTER TABLE [history].[data_Categories] ADD CONSTRAINT [DF_data_Categories_31EC6D26] DEFAULT (newid()) FOR [Id]
GO
ALTER TABLE [history].[data_Categories] ADD CONSTRAINT [DF_data_Categories_32E0915F] DEFAULT (getutcdate()) FOR [UpdatedDate]
GO
ALTER TABLE [history].[data_Categories] ADD DEFAULT ('00000000-0000-0000-0000-000000000000') FOR [EntityId]
GO
On a side-note...
You can also turn-off TRIGGERS in your DELETE stored procedures to make the AUDIT "cleaner"
The reason it becomes "cleaner" is you get a single DELETE AUDIT record instead of an UPDATE & DELETE AUDIT record
To do this, just turn off the TRIGGER before the DELETE STATEMENT and turn it on again afterwards.
TABLE TRIGGER:
Just a normal trigger...
CREATE TRIGGER [data].[trig_Categories]
ON [data].[Categories]
AFTER INSERT, DELETE, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Id INT
DECLARE #Type VARCHAR(20);
IF EXISTS(SELECT * FROM INSERTED)
BEGIN
IF EXISTS(SELECT * FROM DELETED)
BEGIN
SET #Type ='UPDATED';
END
ELSE
BEGIN
SET #Type ='INSERTED';
END
INSERT INTO
history.data_Categories (
[EntityId]
,[Name]
,[Description]
,[DisplayOrder]
,[ProductCount]
,[IsActive]
,[UpdatedBy]
,[UpdateType])
SELECT
[Id]
,[Name]
,[Description]
,[DisplayOrder]
,[ProductCount]
,[IsActive]
,[UpdatedBy]
,#Type
FROM INSERTED
END
ELSE
BEGIN
SET #type = 'DELETED';
INSERT INTO
history.data_Categories (
[EntityId]
,[Name]
,[Description]
,[DisplayOrder]
,[ProductCount]
,[IsActive]
,[UpdatedBy]
,[UpdateType])
SELECT
[Id]
,[Name]
,[Description]
,[DisplayOrder]
,[ProductCount]
,[IsActive]
,[UpdatedBy]
,#Type
FROM DELETED
END;
END
GO

Transaction count exception in vb.net (SQL Exception)

I am getting below exception when i am going to enter record in a table through StoredProceduer of sqlserver
i have a field which i need u update immediately after insert of new record in table.
for that i created a sotredprocedure in which i wrote insert command first and after that i wrote a update command for same recored but it gave me below error
SQlException:
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 2. Uncommittable transaction is detected at the end of the batch. The transaction is rolled back. Some Error in stored procedure execution
i tried in another way also like: i just wrote insert command in storedprocedure and i created a afterInsert trigger in which i am firing update command. but still i am facing above exception
Details:
Table structure:
CREATE TABLE [dbo].[TabStoreGRNMaster](
[pk_grnm_id] [bigint] IDENTITY(1,1) NOT NULL,
[fk_col_id] [bigint] NULL,
[fk_sup_id] [bigint] NULL,
[grnm_grnno] [varchar](50) NULL,
[grnm_date] [nvarchar](10) NULL,
[grnm_partyinvno] [varchar](50) NULL,
[grnm_invdate] [nvarchar](10) NULL,
[grnm_freight] [numeric](7, 2) NULL,
[grnm_otherchrg] [numeric](7, 2) NULL,
[grnm_roundoff] [bit] NULL,
[Fk_User_Id] [bigint] NULL,
[grnm_EntryDate] [nvarchar](8) NULL,
CONSTRAINT [PK_TabStoreGRNMaster] PRIMARY KEY CLUSTERED
(
[pk_grnm_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
storedprocedure:
USE [Kollege]
GO
/****** Object: StoredProcedure [dbo].[StoreGRNMaster] Script Date: 11/27/2009 10:20:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[StoreGRNMaster]
(
#pk_grnm_id [bigint] output ,
#fk_col_id [bigint] = 0 ,
#fk_sup_id [bigint] = 0 ,
#grnm_grnno [varchar](50) = '',
#grnm_date [nvarchar](10) = null,
#grnm_partyinvno [varchar](50) = '',
#grnm_invdate [nvarchar](10) = null,
#grnm_freight [numeric] = 0 ,
#grnm_otherchrg [numeric] = 0 ,
#grnm_roundoff [bit] = 0 ,
#Fk_User_Id [bigint] = 0 ,
#grnm_EntryDate [nvarchar](8) = null,
#opt [BIGINT] =0,
#del [bit] =0
)
as
begin
SET NOCOUNT ON;
BEGIN TRY
begin transaction
if isnull(#opt,0) = 0 begin
INSERT INTO TabStoreGRNMaster
(
fk_col_id,
fk_sup_id,
grnm_grnno,
grnm_date,
grnm_partyinvno,
grnm_invdate,
grnm_freight,
grnm_otherchrg,
grnm_roundoff,
Fk_User_Id,
grnm_EntryDate
)
VALUES
(
#fk_col_id,
#fk_sup_id,
#grnm_grnno,
#grnm_date,
#grnm_partyinvno,
#grnm_invdate,
#grnm_freight,
#grnm_otherchrg,
#grnm_roundoff,
#Fk_User_Id,
#grnm_EntryDate
)
set #pk_grnm_id = ##identity
end
else
begin
if #del = 0
UPDATE TabStoreGRNMaster
SET
fk_col_id = #fk_col_id,
fk_sup_id = #fk_sup_id,
grnm_grnno = #grnm_grnno,
grnm_date = #grnm_date,
grnm_partyinvno = #grnm_partyinvno,
grnm_invdate = #grnm_invdate,
grnm_freight = #grnm_freight,
grnm_otherchrg = #grnm_otherchrg,
grnm_roundoff = #grnm_roundoff,
Fk_User_Id = #Fk_User_Id,
grnm_EntryDate = #grnm_EntryDate
WHERE
(
pk_grnm_id = #opt
)
if #del=1 and isnull(#opt,0) <> 0
DELETE from [TabStoreGRNMaster]
WHERE
( [pk_grnm_id] = #opt)
end
commit transaction
END TRY
BEGIN CATCH
raiserror ('Some Error in stored procedure execution',1,1)
END CATCH;
END
Trigger:
alter TRIGGER TGRStoreGRNMasterCode
ON tabStoreGRNMaster
AFTER INSERT
AS
begin
declare #pk varchar(10)
declare #colcode varchar(10)
declare #current_session varchar(20)
declare #colid bigint
set #pk = (select pk_grnm_id from Inserted)
--set #colid = (select fk_col_id from Inserted)
set #colcode= 'jiet'--(select col_code from tabcollegemaster where pk_col_id =5) (when i replace word 'Jiet' with commented qry i gets sql exception otherwise its working fine)
select #current_session = Ses_abbrev from TabAcaSessionMast where ses_current = 1
--update tabStoreGRNMaster set grnm_grnno= #colcode +'/' +#current_session+ '/' + #pk where pk_grnm_id=convert(bigint,#pk)
update tabStoreGRNMaster set grnm_grnno= (select col_code from tabcollegemaster where pk_col_id=5) +'/' +#current_session+ '/' + #pk where pk_grnm_id=convert(bigint,#pk)
end
Your comment to another answer mentioned "I am maintain Transactions from Vb.net also while calling this stored procedure". This is the cause
You have to balance your BEGIN TRAN and COMMITs/ROLLBACKs so ##TRANCOUNT starts and finishes with the same value for the same scope.
Either do it all in the stored proc or do it all in the client
It looks to me like you're not doing anything with the open transaction if an error is found in your TRY block - the COMMIT would not run, but your CATCH block has no ROLLBACK.