I have the following stored procedure in SQL Server:
CREATE PROCEDURE [dbo].[EmptyStagingTableBySupplierNr]
#suppliernumber NVARCHAR(50)
AS
BEGIN
-- routine body goes here, e.g.
-- SELECT 'Navicat for SQL Server'
INSERT INTO proclog (description)
VALUES (#suppliernumber);
DELETE FROM [dbo].[productassortment_staging]
WHERE [LieferantenNr] = #suppliernumber;
INSERT INTO proclog (description)
VALUES ('test');
END
If I execute the stored procedure directly all parts (insert, delete) work fine.
But if I execute the stored procedure from a third party software - only the insert parts are working.
I simplified the stored procedure:
CREATE PROCEDURE [dbo].[EmptyStagingTableBySupplierNr]
#suppliernumber NVARCHAR(50)
AS
BEGIN
-- routine body goes here, e.g.
-- SELECT 'Navicat for SQL Server'
INSERT INTO proclog (description)
VALUES (#suppliernumber);
DELETE FROM [dbo].[productassortment_staging]
WHERE [LieferantenNr] = '123';
INSERT INTO proclog (description)
VALUES ('test');
END
The same result: it works, if I execute it directly, but from the third party software only the insert parts are working.
I have changed the used credentials to the admin account. No change - so
a problem with insufficient rights could be excluded.
Any ideas how I can solve the problem?
I have the following procedure, which I don't want SQL to show affected row counts:
CREATE PROCEDURE UP_STOREDPROC #field VARCHAR(15)
AS
SET NOCOUNT ON;
INSERT INTO MYTABLE (field) VALUES (#field);
GO
And a C project using unixODBC/FreeTDS to execute this proc after a prepared statement (SQLPrepare).
After the preparation, when it executes the statement by calling SQLExecute, it always return SQL_NO_DATA (100).
But, from ODBC documentation:
If SQLExecute executes a searched update, insert, or delete statement
that does not affect any rows at the data source, the call to
SQLExecute returns SQL_NO_DATA.
So, it's not a searched insert. If the first line of the procedure is changed to SET NOCOUNT OFF then everything works fine.
What is wrong?
This is running on SQL Server 2008, but the database is in SQL Server 2000 compatibility mode (this I cannot change).
A temporary table is created at the beginning of the stored procedure and then insert into via an EXEC statement from dynamically generated SQL. How is this executing successfully, even though the temporary table (should be, from my understand) is out the execution scope, or does this get bypassed temporarily when performing these statements inside a stored procedure?
Example below:
CREATE PROCEDURE myProc (Param1 int....)
AS
BEGIN
Declare #SQL varchar(max) = null
Create table #tempTable
(
ID int,
Code1 varchar(255),
...
)
SET #SQL = 'insert into #tempTable '
+ ...
EXEC(#SQL)
Select * from #tempTable
END
Any help understanding this would be greatly appreciated!
Thanks!
Shortly:
The temporary table created in the outer batch is accessible inside the dynamic SQL but not vice versa.
See doc
A local temporary table created in a stored procedure is dropped
automatically when the stored procedure is finished. The table can be
referenced by any nested stored procedures executed by the stored
procedure that created the table. The table cannot be referenced by
the process that called the stored procedure that created the table.
I have two different SQL 2008 servers, I don't have permission to create a linked server in any of them.
i created a trigger on server1.table1 to insert the same record to the remote server server2.table1 using OPENROWSET
i created a stored procedure to insert this record, and i have no issue when i execute the stored procedure. it insert the recored into the remote server.
the problem is when i call the stored procedure from trigger, i get an error message.
can anyone help me please to solve this issue
Stored Procedure:
USE [DB1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROCEDURE [dbo].[InsertIntoRemoteTable]
#Description nvarchar(50)
AS
insert into
OPENROWSET(
'SQLNCLI', 'Server=Server2;UID=MySRV2user;PWD=MySRV2Password',
'SELECT Description FROM [RemoteDB].[dbo].[Table_1]')
SELECT #Description
Trigger:
ALTER TRIGGER [dbo].[InsertTable1]
ON [DB1].[dbo].[Table_1]
for insert
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Desc nvarchar(50)
Select #Desc = i.Descr from INSERTED i;
EXEC InsertIntoRemoteTable #Desc
END
When i try to insert a new description value in the table i got the following error message:
"No row was updated
the data in row 1 was not committed
Error source .Net SqlClient Data provider.
Error Message: the operation could not be performed because OLE DB
provider "SQLNCLI10" for linked server "(null)" returned message "The partner transaction manager has disabled its support for remote/network transaction.".
correct the errors entry or press ESC to cancel the change(s).
can anyone help please on this
thanks
I think you have over complicated this. There is really no need for a stored procedure here to do this. You can do this insert into another database directly in your trigger with a simple insert statement. This removes a ton of complexity and it is set based.
ALTER TRIGGER [dbo].[InsertTable1]
ON [DB1].[dbo].[Table_1]
for insert
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO RemoteDB].[dbo].[Table_1](Description)
Select i.Descr
from INSERTED i;
END
I want to call stored procedure from a trigger,
how to execute that stored procedure after x minutes?
I'm looking for something other than WAITFOR DELAY
thanks
Have an SQL Agent job that runs regularly and pulls stored procedure parameters from a table - the rows should indicate also when their run of the stored procedure should occur, so the SQL Agent job will only pick rows that are due/slightly overdue. It should delete the rows or mark them after calling the stored procedure.
Then, in the trigger, just insert a new row into this same table.
You do not want to be putting anything in a trigger that will affect the execution of the original transaction in any way - you definitely don't want to be causing any delays, or interacting with anything outside of the same database.
E.g., if the stored procedure is
CREATE PROCEDURE DoMagic
#Name varchar(20),
#Thing int
AS
...
Then we'd create a table:
CREATE TABLE MagicDue (
MagicID int IDENTITY(1,1) not null, --May not be needed if other columns uniquely identify
Name varchar(20) not null,
Thing int not null,
DoMagicAt datetime not null
)
And the SQL Agent job would do:
WHILE EXISTS(SELECT * from MagicDue where DoMagicAt < CURRENT_TIMESTAMP)
BEGIN
DECLARE #Name varchar(20)
DECLARE #Thing int
DECLARE #MagicID int
SELECT TOP 1 #Name = Name,#Thing = Thing,#MagicID = MagicID from MagicDue where DoMagicAt < CURRENT_TIMESTAMP
EXEC DoMagic #Name,#Thing
DELETE FROM MagicDue where MagicID = #MagicID
END
And the trigger would just have:
CREATE TRIGGER Xyz ON TabY after insert
AS
/*Do stuff, maybe calculate some values, or just a direct insert?*/
insert into MagicDue (Name,Thing,DoMagicAt)
select YName,YThing+1,DATEADD(minute,30,CURRENT_TIMESTAMP) from inserted
If you're running in an edition that doesn't support agent, then you may have to fake it. What I've done in the past is to create a stored procedure that contains the "poor mans agent jobs", something like:
CREATE PROCEDURE DoBackgroundTask
AS
WHILE 1=1
BEGIN
/* Add whatever SQL you would have put in an agent job here */
WAITFOR DELAY '00:05:00'
END
Then, create a second stored procedure, this time in the master database, which waits 30 seconds and then calls the first procedure:
CREATE PROCEDURE BootstrapBackgroundTask
AS
WAITFOR DELAY '00:00:30'
EXEC YourDB..DoBackgroundTask
And then, mark this procedure as a startup procedure, using sp_procoption:
EXEC sp_procoption N'BootstrapBackgroundTask', 'startup', 'on'
And restart the service - you'll now have a continuously running query.
I had kind of a similar situation where before I processed the records inserted into the table with the trigger, I wanted to make sure all the relevant related data in relational tables was also there.
My solution was to create a scratch table which was populated by the insert trigger on the first table.
The scratch table had a updated flag, (default set to 0), and an insert get date() date field, and the relevant identifier from the main table.
I then created a scheduled process to loop over the scratch table and perform whatever process I wanted to perform against each record individually, and updating the 'updated flag' as each record was processed.
BUT, here is where I was a wee bit clever, in the loop over process looking for records in the scratch table that had a update flag = 0, I also added the AND clause of AND datediff(mi, Updated_Date, getdate())> 5. So the record would not actually be processed until 5 minutes AFTER it was inserted into the scratch table.