"select into" in select statement - sql

I need this query inside a select statement in another query, i have tried to put it inside a function and call it from the select, but i get errors maybe because non-scalar statements are not allowed in a function. How can i proceed?
SELECT Tip.NombreTipoMov
INTO #tabla_temp
FROM ut_sgt_Movimientos_t Reg
INNER JOIN ut_sgt_TiposMovimientos_m Tip
ON Reg.id_TipoMov = Tip.id_TipoMov
WHERE Reg.id_Registro = #IdRegistro
DECLARE #data VARCHAR(100)
UPDATE #tabla_temp
SET #data = #data + ' ' + NombreTipoMov
SELECT LTRIM(RTRIM(#data))
DROP TABLE #tabla_temp
This is the function:
CREATE FUNCTION dbo.uf_sgt_ObtieneTiposMovimientosXRegistroVehiculo
(
#IdRegistro INTEGER
)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE #Retorno VARCHAR(100)
SET #Retorno = ( SELECT Tip.NombreTipoMov
INTO #tabla_temp
FROM ut_sgt_Movimientos_t Reg
INNER JOIN ut_sgt_TiposMovimientos_m Tip
ON Reg.id_TipoMov = Tip.id_TipoMov
WHERE Reg.id_Registro = #IdRegistro
DECLARE #data VARCHAR(100)
UPDATE #tabla_temp
SET #data = #data + ' ' + NombreTipoMov
SELECT LTRIM(RTRIM(#data))
DROP TABLE #tabla_temp
)
RETURN #Retorno END GO
This is the error:
Incorrect syntax near the keyword 'INTO'.
Illegal UPDATE statement within a scalar SQL function.
Illegal SELECT statement within a scalar SQL function.
Illegal DROP TABLE statement within a scalar SQL function.
Incorrect syntax near ')'.

Related

Multiple errors in SQL Server Function

I'm trying to make a function that evaluates the expiration date in a policy and based on that when is called in a Query it returns the text values ('Monthly'..and so on). but i'm getting a few errors of type "Incorrect syntax near Begin, declare expecting (.", "Must declare the scalar variable #policybillid" and in the end of the function "Incorrect syntax near ')'.". Any help would be appreciated.
USE [defaultDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID]( #policybillid BIGINT, #companyID BIGINT) Returns TABLE
AS
RETURN (
BEGIN( ***Incorrect syntax near 'BEGIN'. Expecting '(', SELECT, or WITH.***
declare #expiresDates as table(expiredOn date) ***Incorrect syntax near 'declare'.*** Expecting '(', or SELECT.
insert into #expiresDates
select top(2) expiredOn from PolicyPaymentPlan
left join PolicyPaymentPlanFee on PolicyPaymentPlan.paymentPlanID= PolicyPaymentPlanFee.paymentPlanID
where PolicyPaymentPlan.policyBillID = #policybillid --Must declare the scalar variable "#policybillid".
order by cuoteID
select * from #expiresDates
declare #diffMonth int
declare #quota varchar(max) = ''
if((select count(*) from #expiresDates) > 1)
BEGIN
set #diffMonth = DATEDIFF(month, (select top(1) expiredOn from #expiresDates), (select top(1) expiredOn from #expiresDates order by expiredOn desc));
set #quota = ( SELECT
CASE
WHEN #diffMonth =1
then
'Monthly'
WHEN #diffMonth =2 THEN
'bimonthly'
WHEN #diffMonth =3 THEN
'trimonthly '
WHEN #diffMonth =4 THEN
'Four-Monthly'
WHEN #diffMonth =6 THEN
'biannual'
ELSE 'Cash'
END
)
END
) ***Incorrect syntax near ')'.***
There are numerous issues and syntax errors on your existing code. The main one is that an inline Table Valued Function can only have a single SELECT statement and nothing else.
So here is what it should look like.
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID](
#policybillid BIGINT,
#companyID BIGINT
)
RETURNS TABLE
AS RETURN
SELECT Quota =
CASE WHEN COUNT(*) > 1 THEN
CASE DATEDIFF(month, MIN(expiredOn), MAX(expiredOn))
WHEN 1 THEN 'Monthly'
WHEN 2 THEN 'bimonthly'
WHEN 3 THEN 'trimonthly '
WHEN 4 THEN 'Four-Monthly'
WHEN 6 THEN 'biannual'
ELSE 'Cash'
END
END
FROM (
select top (2) expiredOn
from PolicyPaymentPlan pp
join PolicyPaymentPlanFee ppf on pp.paymentPlanID = ppf.paymentPlanID
where pp.policyBillID = #policybillid
order by cuoteID
) pp
;

Incorrect syntax near '<' in SQL Server Scalar Functions

Here is the requirement:
Find all teachers whose FirstName length is less than 5 and the first 3 characters of their FirstName and LastName are the same
I tried this query (Scalar Function):
CREATE OR ALTER FUNCTION dbo.fn_TeacherFirstName (#TeacherID int)
RETURNS NVARCHAR(20)
AS
BEGIN
DECLARE #Result NVARCHAR(20)
SELECT #Result = LEN(FirstName) < 5 AND LEFT(FirstName,3) = LEFT(LastName,3)
FROM dbo.Teacher
WHERE #TeacherID = ID
RETURN #Result
END
To call function:
--CALL FUNCTION
select *, dbo.fn_TeacherFirstName (ID) AS Result
from dbo.Teacher t
But, when I execute first query, it shows error:
Incorrect syntax near '<'.
Can anyone help me with this?
Just use a normal query, not a function. Also there is no boolean type in SQL Server, use bit instead.
SELECT *,
Result = CAST(CASE WHEN LEN(t.FirstName) < 5 AND LEFT(t.FirstName, 3) = LEFT(t.LastName, 3) THEN 1 END AS bit)
FROM dbo.Teacher t

Subquery as parameter into SQL Server UDF

My question is similar to this.
I made a scalar function like follows:
CREATE FUNCTION [dbo].[MyFunction](#table [TableModel] READONLY)
RETURNS DECIMAL(18, 6) AS
BEGIN
DECLARE #sql NVARCHAR(MAX), #params NVARHCAR(MAX), #value DECIMAL(16, 8);
SELECT #sql = formula, #params = params FROM formulas WHERE id = (SELECT TOP 1 id_formula FROM #table)
EXEC sp_executesql #sql, #params, #table=#table, #value=#value OUTPUT;
RETURN #value;
END
Where a formula SQL could be something like:
SELECT #value = SUM(value) / AVG(value) FROM #table
And it could have more columns if needed.
The model table looks like so:
CREATE TYPE [dbo].[TableModel] AS TABLE(
[formula] INT NOT NULL,
[value] DECIMAL(16, 8) NOT NULL
)
And I want to use it like so:
SELECT od.id, od.col1, od.col2,
dbo.MyFunction((SELECT id.formula, id.value FROM #raw_data id WHERE id.id = od.id)) as result
FROM #data od
GROUP BY od.id, od.col1, od.col2
Where the ID unique and multiple rows will have the same id.
Basically, what I'm trying to do in a single query I want to call a function that has a table parameter. But I want this table to be a subquery.
I'm aware that you can call the function with a table variable as mentioned in this answer.
Is this possible in any way? I'm having this error at executing:
Msg 116, Level 16, State 1, Line 30
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

getting error while RETURN two statement - sql function

ALTER FUNCTION [dbo].[UDF_GetExpenseDetails](#EmpID nvarchar(50))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #ExpAmount nvarchar(MAX)
DECLARE #ExpName nvarchar(MAX)
IF (#EmpID <> '')
BEGIN
SELECT distinct
#ExpAmount = SE.ExpenseAmount, #ExpName = ME.ExpenseName
FROM
tbl_admin_supplierempexpense SE, tbl_master_expense ME
WHERE
SE.EmpID = #EmpID
AND SE.ExpenseName = ME.ExpenseID
AND SE.Status = 'P'
END
RETURN #ExpAmount,#ExpName
END
ERROR : Incorrect syntax near ','.
You can not return more than 1 values from a FUNCTION. If you want multiple values, create a table-valued function.
See it here http://technet.microsoft.com/en-us/library/ms191165.aspx , example included
What if you try this?
CREATE FUNCTION [owner].[UDF_GetExpenseDetails](#EmpID nvarchar(50))
RETURNS TABLE
AS
RETURN
(
SELECT <column1, column2>
FROM <table>
WHERE <condition>
);
Try this
ALTER FUNCTION [dbo].[UDF_GetExpenseDetails](#EmpID nvarchar(50))
RETURNS #table( #ExpAmount money,#ExpName varchar(100))
As
begin
IF (#EmpID <> '')
BEGIN
insert into #ExpAmount
SELECT distinct SE.ExpenseAmount,ME.ExpenseName
from tbl_admin_supplierempexpense SE, tbl_master_expense ME
where SE.EmpID = #EmpID and SE.ExpenseName=ME.ExpenseID and SE.Status='P'
END
return
END

Calling table-valued-function for each result in query

Say I had a query like this:
SELECT X FROM Table WHERE Y = 'Z'
How could I execute a Stored Procedure using each X from the above query as the parameter?
UPDATE
I have changed the SP to be a Table-valued function instead. So for each call to the function it will return a table. What I need to do is store all these results in perhaps a temp table and have my SP return this table.
SOLUTION
Finally managed to get this to work with some help from #cyberkiwi. Here is my final solution:
DECLARE #Fields TABLE (
Field int)
INSERT INTO #Fields (X) SELECT * FROM tvf_GetFields(#SomeIdentifier)
SELECT * FROM #Fields
CROSS APPLY dbo.tvf_DoSomethingWithEachField([#Fields].Field)
You can generate a batch statement out of it and then EXEC it
DECLARE #sql nvarchar(max)
SELECT #sql = coalesce(#sql + ';', '')
+ 'exec sprocname ' + QuoteName(AField, '''')
FROM Table
WHERE AField2 = 'SomeIdentifier'
AND AField is not null
EXEC (#sql)
Before the edit (to TVF), you could have changed the SP to continue to populate a temp table.
Post-edit to TVF, you can use a cross apply:
SELECT F.*
FROM Tbl CROSS APPLY dbo.TVFName(Tbl.AField) F
WHERE Tbl.AField2 = 'SomeIdentifier'
Which returns all the "table results" from each invocation of Tbl.AField into a single result set