Stored procedure with table valued parameter - sql

I am trying to make a stored procedure that uses a table as input parameter. However it is not working as intended. Steps I've taken:
First I make a user defined table type:
CREATE TYPE y_yhat_tabletype AS TABLE
(
UTC_DT datetime,
y float,
yhat float
);
Then I try to make a stored procedure:
create procedure sp_evaluate_y_yhat
#data y_yhat_tabletype readonly
as
begin
select sum(#data.y) as sum_y, sum(#data.yhat) as sum_yhat
end
But I get the error:
Msg 137, Level 16, State 1, Procedure sp_evaluate_y_yhat, Line 12 [Batch Start Line 0]
Must declare the scalar variable "#data".
Msg 137, Level 16, State 1, Procedure sp_evaluate_y_yhat, Line 12 [Batch Start Line 0]
Must declare the scalar variable "#data".
The select sum(#data.y) as sum_y, sum(#data.yhat) as sum_yhat line is just to get some output while testing and will be replaced with more operations as soon as I get this to work.
Any idea on what I'm missing?

#data is essentially a table, so you need to treat it as such.
Declare as:
create procedure sp_evaluate_y_yhat
(
#data y_yhat_tabletype readonly
)
as
begin
select sum(y) as sum_y, sum(yhat) as sum_yhat
from #data
end
go
It's worth noting that if #data contained many rows, the row estimate might be off as table variables don't get statistics.

Related

How to start user procedure in sql?

I have a SQL Server function which I need to exec. But I tried to call it via select, exec - it throws an error. How to fix that bug and launch that function?
Procedure code
create or alter function mergetext
(#TitleOfCourtesy text,
#FirstName text,
#LastName text)
returns varchar(255)
as
begin
return concat(#TitleOfCourtesy, ' ', #FirstName, ' ', #LastName)
end
select mergetext('a','b','c')
Error message
Msg 156, Level 15, State 1, Procedure mergetext, Line 12 [Batch Start Line 0]
Incorrect syntax near the keyword 'select'.
Msg 195, Level 15, State 10, Procedure mergetext, Line 12 [Batch Start Line 0]
'mergetext' is not a recognized built-in function name.
When calling a SQL Server function, you need to include the schema. If you did not specify a schema when creating the function, then the function is created using your default schema (probably dbo). So try calling the function so:
SELECT dbo.mergetext('a','b','c')
First of all, this is not procedure. It's a function.
Second, the text type is deprecated and should not be used.
Then, you need to separate the creation of the object either using GO, executing it in a separate query window or selecting only the function and pressing F5.
Try this:
create or alter function mergetext(
#TitleOfCourtesy text,
#FirstName text,
#LastName text
)
returns varchar(255)
as
begin
return concat(#TitleOfCourtesy,' ',#FirstName,' ',#LastName)
end
GO
select dbo.mergetext('a','b','c')
and finally, why you are creating a wrapper of the CONCAT function. Just use the CONCAT wherever you need.

Can table parameters be null in a stored procedure and how can I test for inclusion of an item [duplicate]

This question already has an answer here:
Checking if UTD parameter has values in stored procedure
(1 answer)
Closed 3 years ago.
I have a stored proc in SQL Server that accepts a table (dataset) as a parameter like so:
CREATE PROCEDURE [dbo].[blah]
(
#someParm INT,
#someTableParm [dbo].[IntIdType] READONLY,
The type IntIdType is like this:
CREATE TYPE [dbo].[IntIdType] AS TABLE(
[ID] [int] NOT NULL
)
But I need to be able to test to see if the parameter passed is NULL or if it can even be passed as null, and if not, I need to make a special test if it contains zero items
WHERE [SomeParm] = 2 AND
(#someTableParm IS NULL OR EXISTS (SELECT something FROM #someTableParm)) AND ...
I get the error message: Msg 137, Level 16, State 1, Procedure xxxx, Line 58 [Batch Start Line 0]
Must declare the scalar variable "#someTableParm".
Any suggestions?
#someTableParm IS NULL would look for a scalar variable #someTableParm, but your variable a table, so that won't work. Therefore, stick to EXISTS:
WHERE [SomeParm] = 2
AND EXISTS (SELECT 1 FROM #someTableParm)
AND...
If there are no rows in #someTableParm, then the EXISTS will return false. As a quick sample:
CREATE TABLE test (ID int)
INSERT INTO test VALUES(1);
DECLARE #S table (I int);
SELECT *
FROM test
WHERE EXISTS (SELECT 1 FROM #S);
DROP TABLE test;
Notice that the SELECT statement returns no rows.

Table Variables in Azure Data Warehouse

In a SQL Server database, one can use table variables like this:
declare #table as table (a int)
In an Azure Data Warehouse, that throws an error.
Parse error at line: 1, column: 19: Incorrect syntax near 'table'
In an Azure Data Warehouse, you can use temporary tables:
create table #table (a int)
but not inside functions.
Msg 2772, Level 16, State 1, Line 6 Cannot access temporary tables
from within a function.
This document from Microsoft says,
◦Must be declared in two steps (rather than inline): ◾CREATE TYPE
my_type AS TABLE ...; , then ◾DECLARE #mytablevariable my_type;.
But when I try this:
create type t as table (a int);
drop type t;
I get this :
Msg 103010, Level 16, State 1, Line 1 Parse error at line: 1, column:
8: Incorrect syntax near 'type'.
My objective is to have a function in an Azure Data Warehouse which uses a temporary table. Is it achievable?
Edit Start Here
Note that I am not looking for other ways to create one specific function. I have actually done that and moved on. I'm a veteran programmer but an Azure Data Warehouse rookie. I want to know if it's possible to incorporate some concept of temporary tables in an Azure Data Warehouse function.
Ok, I believe this is what you are after.
Firstly, this uses a Table Value Function, which are significantly faster than Scalar or Multi-statement Table value Functions.
Secondly, there was no use for a Table Variable, or Temporary Table, just some good odd string manipulation, a bit of maths, and a CTE. Definitely no expensive WHILE loop.
I've tested this against the examples in the link, and they all return the expected values.
USE Sandbox;
GO
CREATE FUNCTION ValidateHealthNumber (#HealthNumber varchar(10))
RETURNS TABLE
AS
RETURN
WITH Doubles AS(
SELECT CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) AS HNDigit,
CONVERT(tinyint,SUBSTRING(V.HN,O.P,1)) * CASE WHEN O.P % 2 = 0 THEN 1 ELSE 2 END ToAdd
FROM (VALUES(#HealthNumber)) V(HN)
CROSS APPLY (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)) O(P)),
Parts AS (
SELECT CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),1,1)) AS FirstDigit, --We know that the highest value can be 18 (2*9)
CONVERT(tinyint,SUBSTRING(CONVERT(varchar(2),ToAdd),2,1)) AS SecondDigit --so no need for more than 2 digits.
FROM Doubles)
SELECT CASE RIGHT(#HealthNumber, 1) WHEN 10 - RIGHT(SUM(FirstDigit + SecondDigit),1) THEN 1 ELSE 0 END AS IsValid
FROM Parts;
GO
CREATE TABLE #Sample(HealthNumber varchar(10));
INSERT INTO #Sample
VALUES ('9876543217'), --Sample
('5322369835'), --Valid
('7089771195'), --Valid
('8108876957'), --Valid
('4395667779'), --Valid
('6983806917'), --Valid
('2790412845'), --not Valid
('5762696912'); --not Valid
SELECT *
FROM #Sample S
CROSS APPLY ValidateHealthNumber(HealthNumber) VHN;
GO
DROP TABLE #Sample
DROP FUNCTION ValidateHealthNumber;
If you don't understand any of this, please do ask.
No you can't. Object can't be created inside User Defined Functions (UDF). Use table variables instead.
If you want yo use user defined type, first create it outside the UDF and use it as a variable type within the UDF.
-- Create the data type
CREATE TYPE TestType AS TABLE
(
Id INT NOT NULL,
Col1 VARCHAR(20) NOT NULL)
GO
-- Create the tabled valued function
CREATE FUNCTION TestFunction
()
RETURNS
#Results TABLE
(Result1 INT, Result2 INT)
AS
BEGIN
-- Fill the table variable with the rows for your result set
DECLARE #Var1 TestType;
RETURN
END
GO

sql error procedure

What's wrong with this code?
CREATE PROCEDURE Proc
(
#factura_id int, #produs_id int, #pret float, #cantitate int,#nr_ordine int
)
as
--declare #factura_id int, #produs_id int, #nr_ordine int, #pret float, #cantitate int
begin
if(((select COUNT (id_produs) from Produse where id_produs=#produs_id)=1))
insert into FacturaProdus(id_factura,id_produs,pret,cantitate,nr_ordine)
values(#factura_id,#produs_id,#pret, CONCAT ('-',convert(float,#cantitate),#nr_ordine))
else
begin
print 'hei'
end
end
I can't find a solution for this.When i execute it, it gives me:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'Proc'.
Msg 137, Level 15, State 2, Line 8
Must declare the scalar variable "#produs_id".
Msg 137, Level 15, State 2, Line 9
Must declare the scalar variable "#factura_id".
What to do?
Proc is reserved word in SQL server (I assume you're using it based on syntax and error messages).
So if you really want to create procedure having such a name (I recommend you to choose another name, though) - enclose it into square brackets:
CREATE PROCEDURE [Proc]
(
.....

procedure does not know custom type

I'm having a procedure and some custom types to pass some data to it:
CREATE TYPE StringList AS TABLE
(Value NVARCHAR(255));
GO
CREATE TYPE KeyValueList AS TABLE
(
Id uniqueidentifier,
Value NVARCHAR(255));
GO
CREATE PROCEDURE
#update_AttributeFormel(
#modelPrefix NVARCHAR(255),
#definitionNeutralName NVARCHAR(255),
#newFormula NVARCHAR(255),
#providersToRemove StringList READONLY,
#providersToAdd KeyValueList READONLY)
AS ....
The ManagementStudio does not show any error (as it would when i comment out the type declaration) but when i execute the script, i'm getting the following errors:
Msg 2715, Level 16, State 3, Procedure #update_AttributeFormel, Line 2
Column, parameter, or variable #4: Cannot find data type StringList.
Parameter or variable '#providersToRemove' has an invalid data type.
Msg 2715, Level 16, State 3, Procedure #update_AttributeFormel, Line 2
Column, parameter, or variable #5: Cannot find data type KeyValueList.
Parameter or variable '#providersToAdd' has an invalid data type.
Implementation as explained here:
http://www.simple-talk.com/sql/t-sql-programming/temporary-tables-in-sql-server/
http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters
Does anyone have an idea why this happens?
I am pretty sure it is due to creating the procedure in the tempdb space, using CREATE PROCEDURE #update_AttributeFormel. See this SQL Fiddle where it is working perfectly when the types and the procedure are in the same database.
The code is replicated below:
CREATE TYPE StringList AS TABLE
(Value NVARCHAR(255));
GO
CREATE TYPE KeyValueList AS TABLE
(
Id uniqueidentifier,
Value NVARCHAR(255));
GO
CREATE PROCEDURE update_AttributeFormel(
#modelPrefix NVARCHAR(255),
#definitionNeutralName NVARCHAR(255),
#newFormula NVARCHAR(255),
#providersToRemove StringList READONLY,
#providersToAdd KeyValueList READONLY)
AS
SELECT * FROM #providersToRemove
GO
declare #SL StringList;
insert #SL select 'abcdef' union all select 'ok';
declare #KVL KeyValueList;
exec update_AttributeFormel null,null,null,#SL,#KVL;
You have to create the custom data type in tempdb for it to be recognized in a different database.