SQL Server stored procedure: Must declare the scalar variable - sql-server

DECLARE #occurrences TABLE (Occurrences int)
BEGIN
SET #occurrences = (SELECT Occurrences FROM [Data])
END
Why this is not possible to execute? I want to read into a table all the columns of a given table within my stored procedure so I can update later another table.
Is this fundamentally wrong?
The exact error that SQL Server throws is:
Must declare the scalar variable "#occurrences"

Table variables are different than scalar variables. So you need
DECLARE #occurrences TABLE (Occurrences int)
BEGIN
insert #occurrences
SELECT Occurrences FROM [Data]
END

Related

Snowflake sql Procedure

Am trying to create a procedure using sql in snowflake,but its giving an error when calling it.
create or replace procedure get_max_date( )
returns datetime not null
language sql
as
$$
begin
set max_date= (select max(last_updated) from Control_Variables);
return max_date;
end
$$;
Error:SQL compilation error: error line 5 at position 9 invalid
identifier 'MAX_DATE'
please give me a solution ,actually i want to declare a variable inside proc and store data in that variable as shown in procedure
Regards,
Nadeem
Tried to create snowflake procedure
Indeed, you need to declare your variable inside the procedure. Try this:
create or replace procedure get_max_date( )
returns datetime not null
language sql
as
$$
declare
max_date datetime;
begin
max_date := (select max(last_updated) from Control_Variables);
return max_date;
end
$$;
Example how it works with some test data:
create or replace table Control_Variables (last_updated datetime);
insert into CONTROL_VARIABLES values ('2022-11-28 23:59:59');
insert into CONTROL_VARIABLES values (current_timestamp());
call get_max_date();

Getting Error Msg: Must declare the scalar variable

I used this code in SQL Server:
CREATE TYPE ExampleType AS TABLE (Number INT)
GO
CREATE FUNCTION GetExampleTableType(#InputNumber INT)
RETURNS ExampleType
AS
BEGIN
DECLARE #OutputTable ExampleType;
INSERT INTO OutputTable
VALUES (#InputNumber);
RETURN(#OutputTable);
END;
GO
But I got an error:
Must declare the scalar variable "#OutputTable"
I have declared #OutputTable but it cannot be a scalar value, it must be a table.
What is wrong?
You are trying to return table variable from scalar valued User defined function. You need to convert the function as given below to store the values into the table valued parameter.
Also, read this StackOverFlow Post, where you cannot return UDT from table valued function.
CREATE TYPE ExampleType AS TABLE (Number int)
GO
CREATE Function GetExampleTableType(#InputNumber int)
RETURNS Table
AS
RETURN
(SELECT #InputNumber AS int);
DECLARE #OutputTable ExampleType
INSERT INTO #OutputTable
SELECT * FROM dbo.GetExampleTableType (1);
Actually you don't need to create a user-defined table type. You can directly give table instead of that.
Query
CREATE Function GetExampleTableType(#InputNumber int)
RETURNS #OutputTable TABLE
(
Number int
)
AS
BEGIN
INSERT INTO #OutputTable VALUES (#InputNumber);
RETURN;
END;
As per my understanding we can use tabletype variables to pass as arguments to functions and stored procedures but not used in multistatemnet table valued functions like you mentioned in the question. But in your example you try to access tabletype variable in returns clause which is syntactically incorrect.
This is what i have as sample code here to use tabletype variables in functions context.. please let me know if any thing i missed to understand your question...
CREATE TYPE TableType
AS TABLE (LocationName VARCHAR(50))
GO
CREATE FUNCTION Example( #TableName TableType READONLY)
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #name VARCHAR(50)
SELECT #name = LocationName FROM #TableName
RETURN #name
END
DECLARE #myTable TableType
INSERT INTO #myTable(LocationName) VALUES('aaa')
SELECT dbo.Example(#myTable)
Table-valued parameters have the following restrictions:
SQL Server does not maintain statistics on columns of table-valued parameters.
Table-valued parameters must be passed as input READONLY parameters to Transact-SQL routines. You cannot perform DML operations such as UPDATE, DELETE, or INSERT on a table-valued parameter in the body of a routine.
You cannot use a table-valued parameter as target of a SELECT INTO or INSERT EXEC statement. A table-valued parameter can be in the FROM clause of SELECT INTO or in the INSERT EXEC string or stored procedure.
Reference: https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine?view=sql-server-2017

Accessing temp table created within a stored procedure outside of procedure but within same transaction

I have a transaction that calls a stored procedure which creates a temp table. I need to be able to access this temp table outside of the stored procedure after it has been ran. Note: for what I am trying to do, I cannot use global temp tables.
Example:
Here is an example of the stored procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
IF OBJECT_ID('tempdb..#CurrentChangeID') IS NOT NULL
DROP TABLE #CurrentChangeID
SELECT '00000000-0000-0000-0000-000000000000' AS ChangeID INTO #CurrentChangeID
END
GO
Here is an example of the transaction:
BEGIN TRANSACTION
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID
DECLARE #test uniqueidentifier
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
COMMIT TRANSACTION
GO
The issue is that it cannot find a table named #CurrentChangeID.
How can I make it to where it can see this table without declaring it as a global temp table such as ##CurrentChangeID?
------UPDATE------
So let me give more context to my question because that was just a simplified example. So what I am ultimately trying to do is this: 1. Begin Transaction 2. Call stored procedure that generates the GUID 3. Then update row in a given view that has a trigger. 4. Within that trigger get the GUID that was generated within the sp. 5. Commit.
First of all you can't get access to local temp table defined in SP outside stored procedure. It will always be out of scope.
Second you probalbly don't even need temp table. In your example:
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
it looks like you want only one value.
I propose to use output parameter.
CREATE PROCEDURE [dbo].[GetChangeID](
#test UNIQUEIDENTIFIER OUTPUT
)
AS
BEGIN
-- ...
SET #test = '00000000-0000-0000-0000-000000000000';
END;
And call:
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID #chaneId OUTPUT;
SELECT #changeId;
Thank you lad2025 and Dan Guzman for your input. The way I was originally trying to do this was definitely incorrect.
I did, however, figure out a way to accomplish this task.
Modified Stored Procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
DECLARE #ChangeID uniqueidentifier
...
Code that generates the uniqueidentifier, #ChangeID.
...
--This can be seen within the context of this batch.
SET CONTEXT_INFO #ChangeID
END
GO
Then anywhere within this transaction that you would like to access the changeID, you just have to use the following query:
SELECT CONTEXT_INFO as changeID
FROM sys.dm_exec_requests
WHERE session_id = ##SPID AND request_id = CURRENT_REQUEST_ID()

Pass test data to table-valued parameter within SQL

Is it possible, and if so how, to pass data to a table-valued parameter of a stored function using SQL EXEC?
I know how to pass in data from C#. One of my four stored procs using table-valued parameters is not producing the expected results. I'd like to execute my proc from SQL server management studio for debugging purposes, but I am unable to find the correct syntax for doing so, if such a syntax even exists. I haven't found anything relevant in the docs.
My type table:
CREATE TYPE [MyNameSpace].[MyTypeTable] AS TABLE(
//... all my fields
)
My stored proc:
//... bunch of stuff
ALTER PROCEDURE [MyNameSpace].[MyStoredProc]
#MyTypeTableVar MyTypeTable READONLY
AS
BEGIN
//Do a bunch of stuff
//Want to test the stuff in here
END
I have tried:
IF OBJECT_ID('tempdb.dbo.#MyTempTable') IS NOT NULL DROP TABLE tempdb.dbo.#MyTempTable;
select top 0 *
into #MyTempTable
//existing table with structure that matches the table-valued param
from MyNameSpace.MyTable;
//...Long insert statement assigning test data to #MyTempTable
EXECUTE MyNameSpace.MyStoredProc #MyTypeTableVar = #MyTempTable;
which throws:
Operand type clash: nvarchar is incompatible with MyTypeTable
You can't use a temp table - you have to use a table variable:
declare #t [MyNameSpace].[MyTypeTable]
insert into #t (/*columns*/) values
(/* first row */),
(/* second row */)
EXECUTE MyNameSpace.MyStoredProc #MyTypeTableVar = #t;
(You can populate it with either INSERT ... VALUES as shown above or INSERT ... SELECT if you have an existing table containing the data you care about)
Here's a working example:
-- Declare a table parameter
DECLARE #registryUpdates AS typ_KeyValuePairStringTable;
-- Insert one row
INSERT INTO #registryUpdates
VALUES ('Hello', 'World');
-- Call Stored Procedure
EXEC prc_UpdateRegistry #registryUpdates

SQL Server: ltrim on User-Defined Table Types

I have a SQL Server 2012 User-Defined Table Types that I am using to get data from a PHP array and pass that data to a Procedure. Sometimes I get white spaces from the web app and I would like to use ltrim/rtrim to clean it. Can I do this at the User-Defined Table Type level? IE: where I declare that it should expect a parm1 varchar(10) can I somehow trim is there? I haven't had any luck. Thank you
Example, my Table Type looks like this:
CREATE TYPE LocationTableType AS TABLE
( LocationName VARCHAR(50)
, CostRate INT );
GO
I want to change it so that when LocationName comes in, it will ltrim()/rtrim() to clear out any extra spaces.
I assume that reported issue is linked to READONLY property of table valued params, property that is mandatory. This means that rows from table valued params can not be updated/deleted and also we can't insert other rows.
CREATE PROCEDURE dbo.DoSomething
#list dbo.LocationTableType READONLY -- <-- table table param have to be READONLY
AS
BEGIN
SELECT * FROM #list
END
On short term solution could be
1)to declare another variable within stored procedure
2)insert trimmed data into this variable and then
3)to change next references to all variable - param to new variable.
ALTER PROCEDURE dbo.DoSomething
#list dbo.LocationTableType READONLY
AS
BEGIN
DECLARE #listNoSpc dbo.LocationTableType -- New variable
INSERT #listNoSpc (LocationName, CostRate) -- Inserting trimmed data
SELECT LTRIM(l.LocationName), l.CostRate
FROM #list l
SELECT * FROM #listNoSpc -- Update references from #list to #listNoSpc
END
GO
Permanent solution should be to update webapp (PHP) to remove those spaces before sending data to SQL Server.

Resources