Convert to int with data style NULL - sql

After upgrading from SQL Server 2012 to SQL Server 2017 a stored procedure feeding a quarterly report is failing to provide information. Identified the issue as the procedure is failing to generate a variable that drives the rest of the procedure.
Identified the variable wasn't being set due to a CONVERT statement using the data style NULL. If the query below is run on SQL Server 2017 the variable #CountFrequency returns NULL, as expected based on the Microsoft Doc regarding CONVERT and data style NULL. If that query is run on SQL Server 2012 or 2016 #CountFrequency returns 4, which allowed the stored procedure to run successfully in our production environment prior to the upgrade.
DECLARE #OwnerCountUDF varchar(30) = '4'
, #CountFrequency int
;
IF ISNUMERIC(#OwnerCountUDF) = 1
SELECT #CountFrequency = CONVERT(int,#OwnerCountUDF,NULL)
ELSE
SELECT #CountFrequency = 1
;
SELECT ISNUMERIC(#OwnerCountUDF) 'Numeric'
, #OwnerCountUDF '#OwnerCountUDF'
, #CountFrequency '#CountFrequency'
;
Have been unable to find any documentation about a change to CONVERT which would cause this difference in results.

According to the documentation, which is annotated SQL Server (starting with 2008):
style
An integer expression that specifies how the CONVERT function will translate expression. For a style value of NULL, NULL is returned. data_type determines the range.
Perhaps your compatibility level was set to an even earlier version in the SQL Server 2012 version.

Related

SQL Server: From 2008 To 2014 :-The data types datetime and time are incompatible in the add operator. Any other solution?

I am migrating from SQL Server 2008 To 2014 and I get an error
The data types datetime and time are incompatible in the add operator.
I figured out the solution convert time to DateTime, but I have changes in many stored procedures and views.
Is there any other solution for above problem?
There is no other solution than re-factoring your code if you wish to upgrade to SQL2014. The example below demonstrates that setting the compatibility level to 2008 does not resolve this error. You will have to modify all your stored procedures and views.
ALTER DATABASE database_name SET COMPATIBILITY_LEVEL = 100
GO
--DOESNOT WORK IN 2012
DECLARE #ESTRecords TABLE
(
ESTime TIME(7) NOT NULL ,
ESTDate DATE NOT NULL ,
ESTDateTime AS ( CONVERT(DATETIME, ESTDate, ( 108 )) + ESTime )
PERSISTED
)
INSERT INTO #ESTRecords
( ESTime, ESTDate )
VALUES ( '12:00 PM', '12/31/2012' )
SELECT *
FROM #ESTRecords

How To Determine Column Types In A SQL Server Results Set

I have a stored procedure that I'm executing using SQL Server Management Studio (SSMS) using SQL Server 2014 and I get a results set back. I'm wondering if it's possible to discover the column types. For example, Let's say the results set has the following columns:
Id
Name
BirthDate
Address
State
ZipCode
I want to discover the type of each column (e.g. "Id" is an integer, "Name" is a string, etc.)
Can I do this in SSMS without having to look inside the stored procedure? Is there some SQL statement I can run to find out the column types?
For Sql Server 2012 and up:
EXEC sp_describe_first_result_set N'SELECT * from customer', null, 0;
https://msdn.microsoft.com/en-us/library/ff878602.aspx
If you only need the datatype then try this out. There is also other data type info you can return. Look at the documentation for SQL_VARIANT_PROPERTY()
https://msdn.microsoft.com/en-us/library/ms178550.aspx
SELECT TOP 1 SQL_VARIANT_PROPERTY(ID,'basetype') AS ID,
SQL_VARIANT_PROPERTY(Name,'basetype') AS Name,
SQL_VARIANT_PROPERTY(BirthDate,'basetype') AS BirthDate,
SQL_VARIANT_PROPERTY([State],'basetype') AS [State],
SQL_VARIANT_PROPERTY(Zipcode,'basetype') AS Zipcode
FROM yourTable
Theoretical Results:
ID Name Birthdate State Zipcode
-----------------------------------------------
int varchar datetime varchar int

Error converting data type nvarchar to datetime with stored procedure

[Using SQL Server 2008 R2 Enterprise x64 SP1]
I am trying to use some form of GETDATE() to pass today's date to a stored procedure inside OPENQUERY(), but I keep getting the error
Msg 8114, Level 16, State 1, Procedure spCalcProjection, Line 0
Error converting data type nvarchar to datetime
Here is the code (spCalcProjection takes a datetime):
SELECT top 1 multi FROM OPENQUERY([production], 'exec proddb.dbo.spCalcProjection "GETDATE()"')
If I use 2014-05-22 or any literal in place of GETDATE() then I have no problem and get the correct, expected result. If I use some other functionality like CAST(GETDATE() AS DATE) or CONVERT(varchar, GETDATE(), 112) then I get the above error again.
Conrad, posting original syntax error for GETDATE() without double quotes could help more than you think. I also don't see why would you need to escape the function here. (Sorry, can't add to your thread with Lamak, not enough reputation for comments). Also, why do you need an open query to call your sp? When you say SQL Server 2008 R2, is it both on the calling side and on your [production] server? If the other end is not SQL Server it might not have GETDATE() function. If the other end is SQL Server you don't need OpenQuery.
[UPDATE]
I think I have your answer. You cannot use a function as a parameter for stored procedure. Has nothing to do with open query. What you can do, you can replace that stored procedure with table-valued function. I just tried it and it worked.
Definition:
CREATE FUNCTION TestFun
(
#TestDateParam datetime
)
RETURNS
#RetTable TABLE
(
Line nvarchar(20)
)
AS
BEGIN
INSERT INTO #RetTable
SELECT aString
FROM sometable
WHERE aDate = #TestDateParam
RETURN
END
Call:
SELECT *
FROM dbname.dbo.TestFun(GETDATE())
Got an answer from elsewhere that I will use:
SELECT top 1 multi FROM OPENQUERY([production], 'DECLARE #dt datetime SELECT #dt = GETDATE() exec proddb.dbo.spCalcProjection #dt')
This avoids having to create any additional objects in the db.

Discover SQL Server procedure default parameters using SYS or INFORMATION_SCHEMA tables

Like Oracle, SQL Server supports parameter defaults in stored procedures. Oracle syntax:
CREATE OR REPLACE PROCEDURE p_default (
p_in_number IN number := 0,
p_out_number OUT number,
p_in_varchar IN varchar2 := '0',
p_out_varchar OUT varchar2,
p_in_date IN date := date '1981-07-10',
p_out_date OUT date
)
SQL Server syntax:
CREATE PROCEDURE p_default (
#p_in_number INTEGER = 0,
#p_out_number INTEGER OUT,
#p_in_varchar VARCHAR(10) = '0',
#p_out_varchar VARCHAR(10) OUT,
#p_in_date DATE = '1981-07-10',
#p_out_date DATE OUT
)
With Oracle, I can discover defaults using this query:
SELECT argument_name, defaulted FROM all_arguments WHERE object_id = :proc_id
How can I discover this in SQL Server selecting from sys or INFORMATION_SCHEMA tables? I don't see any useful column in INFORMATION_SCHEMA.PARAMETERS, and the sys.parameters.has_default_value seems not to be set correctly (!)
Note, I have asked as similar question about DB2:
Discover DB2 procedure default parameters using SYSCAT tables
There's no simple way to do it. As the documentation for has_default_value states:
SQL Server only maintains default values for CLR objects in this catalog view; therefore, this column has a value of 0 for Transact-SQL objects. To view the default value of a parameter in a Transact-SQL object, query the definition column of the sys.sql_modules catalog view, or use the OBJECT_DEFINITION system function.
So you'd have to pull the whole stored proc definition out and parse it yourself to determine the value.
Side note: I'd be wary of #p_in_date DATE = '1981-07-10'. I know that the date datatype is a bit more sensible than datetime, but I'm not sure if the above is still ambiguous - certainly if it was converted to datetime, it may result in 10th July or 7th October, depending on language settings. I'd be more comfortable with '19810710' which will always be interpreted as 10th July.

Why doesn't SQL2008 interpret the conditional WHERE clause in my stored procedure the way 2005 did?

My procedure was working fine in a 2005 database, but my PC died and when I set it up again I installed 2008 rather than 2005 - now this procedure doesn't return any results. I ask the question about the difference between the 2 versions simply because I have used this logic before and I haven't changed the procedure since I created it and it was working, the only change has been the fact I am now using SQL 2008
I wrote the procedure in Visual Studio and have noticed that when I paste the select statement into the SQL pane for the table that it is restructured and expanded so that each variation that could be expressed by combining the ANDs and ORs.
What I need is to be able to call this procedure optionally passing either parameter; so if I pass only the componentType it should evaluate the final statement part of the statement and use the value passed - if no value was passed then it would match the IS NULL side of the condition.
ALTER PROCEDURE dbo.uspSel_ComponentByType(
#filterText VARCHAR(50) = NULL
, #componentType CHAR(2) = NULL)
AS
SELECT [pkComponentID], [ComponentType], [ComponentName], [fkSupplierID], [Cost], [WastageCost]
FROM [tblComponents] AS c INNER JOIN
[tblSuppliers] AS s ON [c].[fkSupplierID] = [s].[pkSupplierID]
WHERE ([ComponentName] LIKE #filterText + '%' OR [SupplierName] LIKE #filterText + '%')
AND [c].[IsDeleted] = 0
AND (#componentType IS NULL OR [ComponentType] = #componentType)
I'm no SQL pro, but if I understand your intentions right, you should be able to use the sproc with no/either/both parameters and get expected results if you default #filterText to '' instead of NULL.
ALTER PROCEDURE dbo.uspSel_ComponentByType(
#filterText VARCHAR(50) = '' ,
#componentType CHAR(2) = NULL
)
AS
SELECT ... --the rest of the sproc is unchanged
As David M clarified, this is probably because SQL Server 2005 and 2008 handles string concatenation with NULL values differently. It seems that in SQL Server 2005
'A string' + NULL = 'A string';
while in SQL Server 2008
'A string' + NULL = NULL;
By changing the default to '', we made the default comparison '' + '%', which will always be treated as % and match everything, instead of NULL + '%', which will end upp NULL and match nothing.
Looks like different default handling of concatenating a null value - it is now concatenating NULL with '%' to give NULL, causing the LIKE comparison to fail. If you replace the NULL default with an empty string for #filterText you have a stored procedure that is not affected by such a difference in behaviour.
I guess it's due to SET options, especially likely is CONCAT_NULL_YIELDS_NULL, with ANSI_NULLS as a bubbler