SQL scalar function msg 107 after upgrade to 2019 - tsql

I have a really simple scalar function with the following code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetNDate_YYYYMM]
(
#InputDate DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE #RIS AS INT
SET #RIS=NULL
IF (#InputDate IS NOT NULL) SET #RIS=(YEAR(#InputDate)*100)+(MONTH(#InputDate))
USCITA:
RETURN #RIS
END
This function has worked for years in SQL 2012 but now I have migrated the function to SQL 2019 I get the following message:
Msg 107, Level 15, State 1, Procedure GetNDate_YYYYMM, Line 1 [Batch Start Line 0]
The column prefix 'DT0' does not match with a table name or alias name used in the query.
In reality if I run a select on this function from the SQL management studio (and not during a stored procedure, where I first noticed the problem) I get this message only on the first run and then it doesn't appear until I reconnect to the DB.
Thanks for the help,
James

This looks like a scalar UDF inlining bug in 2019 RTM that has been fixed already in some cumulative update (quite likely CU2 as that fixed the below issue and you have such a label)
UDFs referencing labels without an associated GOTO command return
incorrect results (added in Microsoft SQL Server 2019 CU2)
It looks like some internal error that is mistakenly returned to the client but not actually treated as an error.
For the following SQL
BEGIN TRY
SELECT [dbo].[GetNDate_YYYYMM]('1900-01-01') AS FunctionResult
OPTION (RECOMPILE)
SELECT 'After UDF' AS Message
END TRY
BEGIN CATCH
SELECT 'In Catch' AS Message
END CATCH
The output with "Results to Text" selected is
Msg 107, Level 15, State 1, Procedure GetNDate_YYYYMM, Line 1 [Batch Start Line 21]
The column prefix 'DT0' does not match with a table name or alias name used in the query.
Msg 107, Level 15, State 1, Procedure GetNDate_YYYYMM, Line 1 [Batch Start Line 21]
The column prefix 'DT0' does not match with a table name or alias name used in the query.
FunctionResult
--------------
190001
Message
---------
After UDF
So the function result is returned successfully after the error message and execution continues without the CATCH block being reached.
Some possible resolutions to this
remove the problem label (USCITA:)
add INLINE=OFF to the function to disable inlining
upgrade to the latest CU to get the latest bug fixes

You could also avoid using a function :P
This returns the same thing :)
DECLARE #InputDate DATETIME = GETDATE()
SELECT FORMAT(#InputDate,'yyyyMM')
--202006
Interesting bug. I ran on my local SQL2019, same error.
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) Sep 24 2019
13:48:23 Copyright (C) 2019 Microsoft Corporation Developer Edition
(64-bit) on Windows 10 Pro 10.0 (Build 15063: )
The column prefix 'DT0' does not match with a table name or alias name
used in the query.
but db<>fiddle works fine https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=100c7cb025acfdeaa3fbf1093e91102b

Related

FB3.0 Dateadd() throws syntax error in where section of query

I am trying to compare the date modified (field type: Timestamp) with a value that is based off of a month before the current date. I keep getting a syntax error when using the function DateAdd().
I Am Using Libreoffice base 6.2.3.2 (x64) and firebird 3.0 embedded
Using this code, I get a result returning no records but no error
Select *
From "tblPart"
Where "Date Modified" = Current_Timestamp
but anytime I want to use the Dateadd() function, I get an error
Select *
From "tblPart"
Where
"Date Modified"< Dateadd(Month,-1,Current_Timestamp)
Expected to Return a list of results that have been modified over a month ago.
Errors:
SQL Status: HY000
Error code: 1000
Syntax error in SQL statement
SQL Status: HY000
Error code: 1000
SQL Status: HY000
Error code: 1000
syntax error, unexpected $end, expecting BETWEEN or IN or SQL_TOKEN_LIKE
//EDIT: Added the programs that I used
I ran into the same problem. Though the SQL-statement with DateAdd() has been suggested as working, LO Base answered the query with a message box
Syntax error in SQL statement
Why it should work
In contrast the same SQL statement like in the query succeeded by running it in the "Execute SQL Statement" window (LO Base' main window menu "tools" > "SQL…").
Solution
What finally got my query to work was to check "Run SQL command directly" in the toolbar or in the "Edit" menu.
This prevents LO from analyzing the SQL query before execution. This fails, because it is not understanding the full SQL statement (firebird's DateAdd()-function), and thus is the reason for the mentioned errors.

I can create a stored procure with invalid user defined function names in it

I just noticed that I could alter my stored procedure code with a misspelled user defined function in it.
I noticed that at 1st time I execute the SP.
Is there any way to get a compile error when an SP include an invalid user-defined function name in it?
At compile time? No.
You can, however, use some of SQL's dependency objects (if using MS SQL) to find problems just after deployment, or as part of your beta testing. Aaron Bertran has a pretty nice article rounding up the options, depending upon the version of SQL Server.
Here is an example using SQL Server 2008 sys object called sql_expression_dependencies
CREATE FUNCTION dbo.scalarTest
(
#input1 INT,
#input2 INT
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE #ResultVar int
-- Add the T-SQL statements to compute the return value here
SELECT #ResultVar = #input1 * #input2
-- Return the result of the function
RETURN #ResultVar
END
GO
--Fn Works!
SELECT dbo.ScalarTest(2,2)
GO
CREATE PROCEDURE dbo.procTest
AS
BEGIN
SELECT TOP 1 dbo.scalarTest(3, 3) as procResult
FROM sys.objects
END
GO
--Sproc Works!
EXEC dbo.procTest
GO
--Remove a dependency needed by our sproc
DROP FUNCTION dbo.scalarTest
GO
--Does anything have a broken dependency? YES
SELECT OBJECT_NAME(referencing_id) AS referencing_entity_name,
referenced_entity_name, *
FROM sys.sql_expression_dependencies
WHERE referenced_id IS NULL --dependency is missing
GO
--Does it work? No
EXEC dbo.procTest
GO

Multiple Search in SSRS when using only a part of the field

I Have created a stored procedure:
#DeviceID nvarchar(20) =''
WITH EXECUTE AS CALLER
AS
SELECT
amd.BRANDID,
amd.DEVICEID
FROM AMDEVICETABLE amd
where
left(amd.Deviceid,len(#DeviceID)) in (#DeviceID)
The length of amd.Deviceid is about 15 characters
In Visual Studio I create a parameter #DeviceID and when I am entering e.g ABCDE ( the first 5 characters from Deviceid) everything is working perfect.
the problem is that I want to put multiple values like
jhmcl*, jhmgd*.
So I created my own little version of your report and I believe the problem is your LEN() function. I'm surprised it doesn't return an error because it errors out in Report Builder for SQL Server 2014(simple version of SSRS). I would test what your LEN(#DeviceID) is returning. I would bet it's not returning the correct value. Instead you might try this to cover every possible pattern. I don't know how it will work performance wise.
SELECT DeviceID
FROM YourTable
WHERE LEN(DeviceID,1) IN (#DeviceID)
OR LEN(DeviceID,2) IN (#DeviceID)
OR LEN(DeviceID,3) IN (#DeviceID)
..
OR LEN(DeviceID,15),IN(#DeviceID)

SQL Server 2008 Function for Current Academic Year

I work at a college in London and for some reason no one has added a function to call the current academic year within our SQL Server 2008 instance. I had done this successfully in the past on an Oracle server so I thought, how hard can it be, right?
It is only after a failed attempt of my own I realize it isn't as easy as I thought it would be.
My code so far:
USE [DashboardData]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [fea].[current_academic_year]
()
RETURNS int
AS
BEGIN
DECLARE #Result as int
IF Month(GETDATE())<8
SET #Result= Year(GETDATE())-1
ELSE
SET #Result = Year(GETDATE())
RETURN #Result
END
Now, that looks simple enough to me - and it compiles. However, when I call the function in a simple query (on the same database):
Select fea.[current_academic_year]
I get the following error message:
Msg 4104, Level 16, State 1, Line 1 The multi-part
identifier "FEA.current_academic_year" could not be bound.
Having hardly ever used SQL Server before and after consulting Google, work-colleagues (who stare off into the distance) and former colleagues I am still without an answer. How and why is this happening?
Change:
Select fea.[current_academic_year]
To this:
SELECT [fea].[current_academic_year]()
You are missing (), remember this is a scalar-valued function, not a column name.

How do I rename a tSQLt test class?

I'm developing a database using the Red Gate SQL Developer tools. SQL Test, the SSMS add-in that runs tSQLt tests, lacks a way to rename test classes.
I have a test called [BackendLayerCustomerAdministrationTests].[test uspMaintainCustomerPermissions throws error when PermissionValue is missing or empty].
The name is so long it breaks Deployment Manager.
2013-12-05 18:48:40 +00:00 ERROR The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
There are other unwieldly test names in this class, so I want to start by shortening the class name.
A more succinct class name would be CustomerTests.
sp_rename is no help here.
EXECUTE sys.sp_rename
#objname = N'BackendLayerCustomerAdministrationTests',
#newname = N'CustomerTests';
Msg 15225, Level 11, State 1, Procedure sp_rename, Line 374
No item by the name of 'BackendLayerCustomerAdministrationTests' could be found in the current database 'ApiServices', given that #itemtype was input as '(null)'.
How do I change it?
tSQLt test classes are schemas with a special extended property.
Cade Roux's great solution for renaming schemas is to create a new schema, transfer all the objects, then drop the old schema.
If we did that here we'd lose the extended property.
Let's adapt it for the tSQLt framework.
How to rename a tSQLt test class
Create a new test class.
EXECUTE tSQLt.NewTestClass
#ClassName = 'CustomerTests';
You should see the old class and the new class together in the tSQLt.TestClasses view.
SELECT *
FROM tSQLt.TestClasses;
Name SchemaId
----------------------------------------- ----------
SQLCop 7
BackendLayerCustomerAdministrationTests 10
CustomerTests 14
Cade used Chris Shaffer's select variable concatenation trick to build a list of transfer statements, and print the result.
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql = #sql +
N'ALTER SCHEMA CustomerTests
TRANSFER BackendLayerCustomerAdministrationTests.' + QUOTENAME(name) + N';' +
CHAR(13) + CHAR(10)
FROM sys.objects
WHERE SCHEMA_NAME([schema_id]) = N'BackendLayerCustomerAdministrationTests';
PRINT #sql;
Ugly, but effective.
Copy the output and execute as a new query.
ALTER SCHEMA CustomerTests
TRANSFER BackendLayerCustomerAdministrationTests.[test uspMaintainCustomer validate merged data];
ALTER SCHEMA CustomerTests
TRANSFER BackendLayerCustomerAdministrationTests.[test uspMaintainCustomerPermissions throws error when PermissionValue is missing or empty];
I've shown only two tests here, but it should work for all of them.
Now drop the old test class.
EXECUTE tSQLt.DropClass
#ClassName = N'BackendLayerCustomerAdministrationTests';
The old class should be gone from view.
SELECT *
FROM tSQLt.TestClasses;
Name SchemaId
----------------------------------------- ----------
SQLCop 7
CustomerTests 14
Run all your tests again to check that it worked.
EXECUTE tSQLt.RunAll;
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Result |
+--+----------------------------------------------------------------------------+-------+
|1|[CustomerTests].[test uspMaintainCustomer throws error on missing APIKey] |Success|
|2|[CustomerTests].[test uspMaintainCustomerPermissions validate merged data] |Success|
|3|[SQLCop].[test Decimal Size Problem] |Success|
|4|[SQLCop].[test Procedures Named SP_] |Success|
|5|[SQLCop].[test Procedures using dynamic SQL without sp_executesql] |Success|
|6|[SQLCop].[test Procedures with ##Identity] |Success|
|7|[SQLCop].[test Procedures With SET ROWCOUNT] |Success|
-------------------------------------------------------------------------------
Test Case Summary: 7 test case(s) executed, 7 succeeded, 0 failed, 0 errored.
-------------------------------------------------------------------------------
Success!
Sorry to come into this so late! I'm a developer who's working on SQL Test.
We've just added the ability to rename test classes to the latest version of SQL Test.
http://www.red-gate.com/products/sql-development/sql-test/
It's now as simple as right clicking on the context menu for a test class, or pressing F2:
Please bear in mind that this option will not appear for old versions of tSQLt. To upgrade, right click on the database to uninstall the framework, then do Add database... to re-add it (the right-most button in the window):
Alternatively, you could just call a new procedure in tSQLt called tSQLt.RenameClass, which is what SQL Test calls behind the scenes.
Please let us know if you have any issues with this!
David
What is your workflow like? If you have all your tests for that test class in one script with exec tSQLt.NewTestClass 'BackendLayerCustomerAdministrationTests' then you can just find and replace the testclass name and you are done.
e.g.
EXEC tSQLt.DropClass 'BackendLayerCustomerAdministrationTests'
GO
EXEC tSQLt.NewTestClass 'CustomerTests'
GO
CREATE PROC [CustomerTests].[test_Insert_AddsACustomer]
AS
etc, etc
This will work because the EXEC tSQLt.NewTestClass 'CustomerTests' will drop all objects in the testclass and they will be recreated as the rest of the script runs.
Simplest is probably:
EXEC tSQLt.RenameClass 'old test class name', 'new test class name';
See the tSQLt docs for RenameClass
It seems Red-gate have added that ability to SQL Test since this question was posted, but the raw SQL code is somehow leaner and cleaner (whether or not you use the excellent SQL Test)