Stored procedure and linked server - sql-server

I have a stored procedure, which contains a simple select statement:
ALTER PROCEDURE [dbo].[TransferAuditRecords]
As
SET NOCOUNT ON
SET XACT_ABORT ON
Declare #UserCode As varchar(50)
DECLARE AuditCursor CURSOR FOR
select top 1 UserCode from [AuditDatabaseServer].AuditDatabase.dbo.dbaudit where auditdate >= '2012-09-04'
Open AuditCursor
FETCH NEXT FROM AuditCursor INTO #UserCode
WHILE ##FETCH_STATUS = 0
BEGIN
Print #Usercode
FETCH NEXT FROM AuditCursor INTO #UserCode
END
Close AuditCursor
Deallocate AuditCursor
There are a few lines of code missing, which I excluded as they are irrelevant to the question.
If I execute the SQL statement without the stored procedure i.e. in SQL Studio Manager 2005 then I get a different output than if I run the stored procedure i.e. the top reference returned is different. Why are the outputs different?
I am fairly sure that the reason for this is because SQL Server uses a different execution plan for compiled code is comparison to code being run in SQL Studio Manager. I wanted to check though.

Use an ORDER BY clause to predictably indicate which row is selected.
e.g. select top 1... order by auditdate
Unrelated:: is the use of a cursor required by part of the code you removed? I guess so, otherwise a simpler "select top 1 #UserCode = UserCode from..." would be enough.

Related

Why is this very simple cursor breaking SQL Server Management Studio?

I have created an item on the Degree table and I want to duplicate that record for 19 other Colleges. I have a really simple cursor, but every time I run it it totally crashes SQL Server Management Studio. Is there a way to rewrite this query (or another query entirely which performs the same INSERT INTO) so that it does not crash (and actually executes)?
DECLARE #Colleges VARCHAR(200)
DECLARE DUPLICATE_DEGREE CURSOR FOR
SELECT CollegeID FROM Colleges WHERE CollegeName <> 'Main Office'
OPEN DUPLICATE_DEGREE
FETCH NEXT FROM DUPLICATE_DEGREE INTO #Colleges
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO Degree
(
DegreeName
, CollegeID
)
SELECT
DegreeName
, #Colleges
FROM Degrees
WHERE DegreeID = 123
END
CLOSE DUPLICATE_DEGREE
DEALLOCATE DUPLICATE_DEGREE
Your script is getting stuck in an infinite loop because you're never advancing the cursor and therefore the value of ##FETCH_STATUS never changes resulting in you adding the same record for the same college ad nauseum. Add FETCH NEXT FROM DUPLICATE_DEGREE INTO #Colleges after the INSERT.
Jake - you don't need a cursor, try this:
DECLARE #DegreeName varchar (256)
SET #DegreeName = SELECT DISTINCT DegreeName from Degrees WHERE DegreeID = 123
INSERT INTO Degree (DegreeName, CollegeID)
SELECT #DegreeName, CollegeID
FROM Colleges WHERE CollegeName <> 'Main Office'

SQL Server Cursor not returning multiple rows to Excel

I asked a few days ago about the correct ways to return multiple rows of results from a SQL Server stored procedure and it was recommended that I use the following
select #var01, #var02
Which seems to work fine until I use it in a loop intending to return multiple rows of data such as my current stored procedure
if(object_id('sp_looga')) is not null
drop procedure sp_looga
go
create procedure sp_looga
as
declare #idno integer
declare #desc char(50)
declare colours_cur cursor for
select co_idno, co_desc from colours
where co_status != 'A'
order by co_idno
open colours_cur
fetch next from colours_cur into #idno, #desc
while ##fetch_status = 0
begin
select #idno, #desc
fetch next from colours_cur into #idno, #desc
end
close colours_cur deallocate colours_cur
go
if I execute this inside SQL Server Admin it seems to work perfectly but when I execute it from excel it only returns one row?
I don't see any need to use a cursor in this case. When you select like that within a cursor you return a series of individual results rather than a single table. While programmatically you could capture each of those results and merge them together I am not sure that you can do that in Excel, nor that you would want to. I would just return the encapsulated query.
if(object_id('sp_looga')) is not null
drop procedure sp_looga
go
create procedure sp_looga
as
select co_idno, co_desc from colours
where co_status != 'A'
order by co_idno
go
As a side note - Unless you need to use a stored procedure, you can just run your query from excel as far as I can see by editing your data connection properties definition to be type SQL and entering command text.
EDIT:
I had a look at your other post. You will need to use Dan Guzman's solution using INSERT...EXEC to share the results of this procedure between Excel and another procedure. You were actually on the right track in your original solution but instead of SELECTing variable names you should have done something like INSERT #TEMP EXEC proc_name. The only caveat is that you need to CREATE your temp table first.

How to get result set of SQL Server stored procedure with parameter in a table or excel?

I have a stored procedure in SQL Server 2008, it accepts parameter and outputs a row with 15 columns. I have 100s of parameters to test with.
I do not want to waste time and execute it with each parameter individually and copy the result into an Excel sheet. I want all of them at once.
Can't I run the stored procedure with all the parameters one by one and get all the result in one table?
I have used cursor, I am providing i/ps but same thing, it gives me a separate table for each parameter and that means I have to copy each row one by one
e.g
declare #field1 int
declare cur CURSOR LOCAL for
SELECT t.PID from dbo.TabletTEST t
where t.Enumber in ( 1,2,3,4,5,6..100
)
open cur
fetch next from cur into #field1
while ##FETCH_STATUS = 0
BEGIN
exec [StoreProcToExecute] #field1
fetch next from cur into #field1
END
close cur
deallocate cur
You can use table valued function with Cross Apply. Please check msdn doc for Cross Apply example https://msdn.microsoft.com/en-us/library/ms175156.aspx

classic asp TSQL no rowset returned

I have some TSQL used in classic asp like this:
Declare #tbl TABLE(some columns)
Declare #somevarables
Declare myCur CURSOR
For
Select something From my_table
Open myCur
Fetch Next From myCur Inti somevarables
While (##Fetch_Status<>-1)
Begin
some processimg
......
Insert Into #tbl(...)
Values(...)
Fetch Next From myCur Inti somevarables
End
Deallocate myCur
Select * From #tbl
The scripts worked well in SQL Query Analyzer. However, when I run it in an ASP page, there's no rowset returned, nor error message.
Who can tell me why?
Thanks!
The problem is that you're inserting multiple times and each time your rows affected count will generate a closed recordset.
Simple fix is to make sure in your T-SQL you first SET NOCOUNT ON;, this will stop the row counts and the only recordset returned will be your end SELECT.

Table Variable inside cursor, strange behaviour - SQL Server

I observed a strange thing inside a stored procedure with select on table variables. It always returns the value (on subsequent iterations) that was fetched in the first iteration of cursor. Here is some sample code that proves this.
DECLARE #id AS INT;
DECLARE #outid AS INT;
DECLARE sub_cursor CURSOR FAST_FORWARD
FOR SELECT [TestColumn]
FROM testtable1;
OPEN sub_cursor;
FETCH NEXT FROM sub_cursor INTO #id;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Log TABLE (LogId BIGINT NOT NULL);
PRINT 'id: ' + CONVERT (VARCHAR (10), #id);
INSERT INTO Testtable2 (TestColumn)
OUTPUT inserted.[TestColumn] INTO #Log
VALUES (#id);
IF ##ERROR = 0
BEGIN
SELECT TOP 1 #outid = LogId
FROM #Log;
PRINT 'Outid: ' + CONVERT (VARCHAR (10), #outid);
INSERT INTO [dbo].[TestTable3] ([TestColumn])
VALUES (#outid);
END
FETCH NEXT FROM sub_cursor INTO #id;
END
CLOSE sub_cursor;
DEALLOCATE sub_cursor;
However, while I was posting the code on SO and tried various combinations, I observed that removing top from the below line, gives me the right values out of table variable inside a cursor.
SELECT TOP 1 #outid = LogId FROM #Log;
which would make it like this
SELECT #outid = LogId FROM #Log;
I am not sure what is happening here. I thought TOP 1 on table variable should work, thinking that a new table is created on every iteration of the loop. Can someone throw light on the table variable scoping and lifetime.
Update: I have the solution to circumvent the strange behavior here.
As a solution, I have declared the table at the top before the loop and deleting all rows at the beginning of the loop.
There are numerous things a bit off with this code.
First off, you roll back your embedded transaction on error, but I never see you commit it on success. As written, this will leak a transaction, which could cause major issues for you in the following code.
What might be confusing you about the #Log table situation is that SQL Server doesn't use the same variable scoping and lifetime rules as C++ or other standard programming languages. Even when declaring your table variable in the cursor block you will only get a single #Log table which then lives for the remainder of the batch, and which gets multiple rows inserted into it.
As a result, your use of TOP 1 is not really meaningful, since there's no ORDER BY clause to impose any sort of deterministic ordering on the table. Without that, you get whatever order SQL Server sees fit to give you, which in this case appears to be the insertion order, giving you the first inserted element of that log table every time you run the SELECT.
If you truly want only the last ID value, you will need to provide some real ordering criterion for your #Log table -- some form of autonumber or date field alongside the data column that can be used to provide the proper ordering for what you want to do.

Resources