SQL Server Bug? - sql-server

I am writing a function to process some CSV data. This is what I have written so far...
CREATE FUNCTION dbo.FGetCommaSeperatedValues(#csv as text)
RETURNS #tblIds TABLE(id int,csvlength int)
AS
BEGIN
DECLARE #csvlength AS int
--SET #csvlength = datalength(#csv);
SET #csvlength = 7685
DECLARE #currentIndex AS int
SET #currentIndex = 0
WHILE #currentIndex < #csvlength
BEGIN
--INSERT INTO #tblIds SELECT #currentIndex,#csvlength
INSERT INTO #tblIds (id,csvlength) values (#currentIndex,#csvlength)
SET #currentIndex = #currentIndex+1
END
RETURN
END
My issue is that when I execute the function, using the following command...
SELECT * FROM FGetCommaSeperatedValues('')
The table returned does not show the results that I expect.
Everything is fine until around row 3624 or so (as expected, id column increments by 1)
Then the values increment erratically.
My colleague tested this code in SQL Server 2008 and everything works fine. This appears to be isolated to SQL server 2000.
Does anyone know of this bug, and/or it's resolution?

In order to gaurantee sort order in SQL Server you must use the ORDER BY clause.
ORDER BY CLAUSE

Related

IsNull behaves differently between Sybase 12.5 and 15.7

I am upgrading an application to connect to Sybase ASE 15.7 database servers instead of 12.5. When I switched it over, a stored procedure's behavior changed which caused problems with the application. I narrowed the cause down to the IsNull function being called inside the procedure.
I found that running IsNull on its own worked fine on 15.7:
select IsNull((SELECT 9 WHERE 5 != 5),-1) -- returns -1
However, trying to assign the return value to a variable did not work:
DECLARE #key_clnt_id_n int
SELECT #key_clnt_id_n = IsNull((SELECT 9 WHERE 5 != 5),-1)
select #key_clnt_id_n -- returns blank
Adding a 'from table' clause makes it work:
declare #eff_d datetime
select #eff_d = IsNull((select '09/09/1990' from db_table db WHERE 5!=5),'01/01/1800')
select #eff_d -- returns '01/01/1800'
But removing the 'from table' clause breaks it:
declare #eff_d datetime
select #eff_d = IsNull((select '09/09/1990' WHERE 5!=5),'01/01/1800')
select #eff_d -- returns blank
Finally, turning on COMPATIBLITY_MODE before executing also fixes it:
declare #eff_d datetime
SET COMPATIBILITY_MODE ON
select #eff_d = IsNull((select '09/09/1990' WHERE 5!=5),'01/01/1800')
SET COMPATIBILITY_MODE OFF
select #eff_d -- returns '01/01/1800'
What is going on in the 15.7 databases that causes this? Is the query in the IsNull causing the whole statement to short-circut and not assign a value to the variable?
Are there other ways to ensure the variable will get set?
Our DBAs worked with Sybase and this issue has been logged as a bug by Sybase: CR 742233, “Queries performing isnull() on a variable assignment may return null when ‘streamlined dynamic SQL’ is enabled.”
The workaround is to disable “streamlined dynamic SQL”.

Executing a SQL statement inside a stored procedure, how to store the result of that SQL statement into a variable for later use?

i need to execute several SQL statements inside an stored procedure, save the result into a variable for later use.
SET NOCOUNT OFF
DECLARE #P TABLE
#P = SELECT d.Periodo
from [SISACT].DEPRECIACIONES d, [SISACT].CONTROL_PERIODO c
where c.vigente = 1 AND d.Periodo = c.periodo
IF ##ROWCOUNT > 0
PRINT 'Periodo ya depreciado'
So later i can do something like this
UPDATE [SISACT].ACTIVOS_FIJOS set ultimo_periodo = #p.periodo ...
I know the #P = SELECT is wrong, i saw an example where they used another stored procedure instead of a SELECT statement, i want to know if this is possible without using a stored procedure. If so, how? I'm just going to use the query once in only one stored procedure so i see no point into putting it in another stored procedure. I'm new to T-SQL and SQL server , i'm learning on my own as well and i'm sorry if this is an stupid question.
P.S: The query in this case should return just one record. I'm using SQL SERVER 2008 Express.
Thank you for any help in advance.
I think that what you want.
SET NOCOUNT OFF
DECLARE #P as CHAR(6)
SELECT p# = d.Periodo from [SISACT].DEPRECIACIONES d, [SISACT].CONTROL_PERIODO c where c.vigente = 1 AND d.Periodo = c.periodo
IF ##ROWCOUNT > 0
PRINT 'Periodo ya depreciado'
and later you can use
UPDATE [SISACT].ACTIVOS_FIJOS set ultimo_periodo = #p

Stored procedure and linked 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.

Stored Procedure Does Not Fire Last Command

On our SQL Server (Version 10.0.1600), I have a stored procedure that I wrote.
It is not throwing any errors, and it is returning the correct values after making the insert in the database.
However, the last command spSendEventNotificationEmail (which sends out email notifications) is not being run.
I can run the spSendEventNotificationEmail script manually using the same data, and the notifications show up, so I know it works.
Is there something wrong with how I call it in my stored procedure?
[dbo].[spUpdateRequest](#packetID int, #statusID int output, #empID int, #mtf nVarChar(50)) AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #id int
SET #id=-1
-- Insert statements for procedure here
SELECT A.ID, PacketID, StatusID
INTO #act FROM Action A JOIN Request R ON (R.ID=A.RequestID)
WHERE (PacketID=#packetID) AND (StatusID=#statusID)
IF ((SELECT COUNT(ID) FROM #act)=0) BEGIN -- this statusID has not been entered. Continue
SELECT ID, MTF
INTO #req FROM Request
WHERE PacketID=#packetID
WHILE (0 < (SELECT COUNT(ID) FROM #req)) BEGIN
SELECT TOP 1 #id=ID FROM #req
INSERT INTO Action (RequestID, StatusID, EmpID, DateStamp)
VALUES (#id, #statusID, #empID, GETDATE())
IF ((#mtf IS NOT NULL) AND (0 < LEN(RTRIM(#mtf)))) BEGIN
UPDATE Request SET MTF=#mtf WHERE ID=#id
END
DELETE #req WHERE ID=#id
END
DROP TABLE #req
SELECT #id=##IDENTITY, #statusID=StatusID FROM Action
SELECT TOP 1 #statusID=ID FROM Status
WHERE (#statusID<ID) AND (-1 < Sequence)
EXEC spSendEventNotificationEmail #packetID, #statusID, 'http:\\cpweb:8100\NextStep.aspx'
END ELSE BEGIN
SET #statusID = -1
END
DROP TABLE #act
END
Idea of how the data tables are connected:
From your comments I get you do mainly C# development. A basic test is to make sure the sproc is called with the exact same arguments you expect
PRINT '#packetID: ' + #packetID
PRINT '#statusID: ' + #statusID
EXEC spSendEventNotificationEmail #packetID, #statusID, 'http:\\cpweb:8100\NextStep.aspx'
This way you 1. know that the exec statement is reached 2. the exact values
If this all works than I very good candidate is that you have permission to run the sproc and your (C#?) code that calls it doesn't. I would expect that an error is thrown tough.
A quick test to see if the EXEC is executed fine is to do an insert in a dummy table after it.
Update 1
I suggested to add PRINT statements but indeed as you say you cannot (easily) catch them from C#. What you could do is insert the 2 variables in a log table that you newly create. This way you know the exact values that flow from the C# execution.
As to the why it now works if you add permissions I can't give you a ready answer. SQL security is not transparent to me either. But its good to research yourself a but further. Do you have to add both guest and public?
It would also help to see what's going inside spSendEventNotificationEmail. Chances are good that sproc is using a resource where it didn't have permission before. This could be an object like a table or maybe another sproc. Security is heavily dependent on context/settings and not an easy problem to tackle with a Q/A site like SO.

SQL Server Stored Proc - What is returned to a variable if no data?

If, using the following code in a MS SQL Server 2008 stored procedure:
DECLARE #PROD_ID VARCHAR(20)
SELECT #PROD_ID = MYTABLE.PROD
FROM MYTABLE
WHERE MYTABLE.DEVID = #DEVCODE
DEVCODE does not exist, what will PROD_ID contain? I've tried printing it, but it prints what seems to be a space. However, testing it for space fails. Also, testing for NULL fails. OR, should I be testing for empty in a different manner?
Thanks for reading
BBz
If the #DEVCODE id doesn't exist then #PROD_ID will remain null.
You can't use COALESCE or ISNULL inside the SELECT #PROD_ID = ... statement because it won't return any records at all.
However, you can do:
DECLARE #PROD_ID VARCHAR(20)
SELECT #PROD_ID = MYTABLE.PROD
FROM MYTABLE
WHERE MYTABLE.DEVID = #DEVCODE
IF (#PROD_ID is null) BEGIN
-- do something
END
#PROD_ID should remain NULL if #DEVCODE does not exist.
Are you testing appropriately using
...#PROD_ID IS NULL...
and not trying to test
...#PROD_ID = NULL...
which would be incorrect?

Resources