SQL Select Statement including SP Call has syntax error - sql

MYTABLE has ID column. However, following query generates syntax error.
SELECT ID FROM MYTABLE
WHERE ID = EXEC MY_SP ID
What do you think is wrong here?

You can't call stored procedures inline like this.
A couple of options include:
1) Execute the stored procedure and store the results in a temp table. Then use that temp table.
e.g.
CREATE TABLE #Example
(
ID INTEGER
)
INSERT #Example
EXECUTE My_SP
SELECT t.ID FROM MyTable t JOIN #Example e ON t.ID = e.ID
DROP TABLE #Example
2) convert the sproc to a user defined function which you CAN call inline
e.g.
CREATE FUNCTION dbo.MyFunc()
RETURNS TABLE
AS
RETURN
(
SELECT ID FROM SomeTable WHERE ....
)
SELECT t.ID FROM MyTable t JOIN dbo.MyFunc() f ON t.ID = f.ID
3) If the sproc returns a single ID, consider returning an OUTPUT parameter from the sproc instead and use like this:
DECLARE #ID INTEGER
EXECUTE MY_SP #ID OUTPUT
SELECT ID FROM MYTABLE
WHERE ID = #ID

I don't think you need the exec statement, just call the sp, exec is expected to be a separate statement

I don't think you can do that at all. Are you perhaps thinking of a User Defined Function rather than a stored Procedure. Based on the context, you'll need a scalar UDF.

Try this:
SELECT ID FROM MYTABLE WHERE ID = ##SPID

Related

Returning a table in firebird 3.0 with stored function or stored procedure

I'm trying to write a stored procedure/function that returns me a table with one or multiple rows of data.
The returned data depends on a variable shown in the following sql statement:
SELECT * FROM table_name AS SD WHERE EXISTS
(SELECT DISTINCT S.PARENT_ID FROM table_name AS S
WHERE S.COMPONENT_ID = 10011 AND S.CARRIER_GROUP_ID = X AND SD.SD_ID = S.PARENT_ID)
So far I have seen that something is done like this:
CREATE FUNCTION f_test_function (X INT)
RETURNS TABLE
AS
RETURN
(SELECT * FROM table_name AS SD WHERE EXISTS
(SELECT DISTINCT S.PARENT_ID FROM table_name AS S
WHERE S.COMPONENT_ID = 10011 AND S.CARRIER_GROUP_ID = X AND SD.SD_ID = S.PARENT_ID));
Afterwards you call the function/procedure with a X value. I know that there is something wrong with the returns type but I don't know what.
Can anyone help?
What you are looking for is a selectable stored procedure. Firebird requires you to explicitly declare the columns the stored procedure returns, so something like returns table is not an option. For example:
create procedure sp_test_procedure (x integer)
returns (column1 integer, column2 varchar(50))
as
begin
for select value1, value2
from table_name SD
where exists (
SELECT DISTINCT S.PARENT_ID
FROM table_name AS S
WHERE S.COMPONENT_ID = 10011
AND S.CARRIER_GROUP_ID = :X
AND SD.SD_ID = S.PARENT_ID)
into column1, column2
do
begin
suspend;
end
end
You will need to explicitly map the columns, so a simple select * is not a good idea.
Note the use of for select, which selects zero or more rows and iterates over the cursor, and suspend, which outputs a row to be fetched from the stored procedure (in this case for each row of the cursor).
You can produce values from this procedure like:
select column1, column2
from sp_test_procedure(10)

Create a function that accepts list of ids?

I would like to do create a SQL function like this (pseudocode):
function PeopleInCompanies(companyIds)
SELECT * from Person WHERE CompanyId IN (companyIds)
end function
and call it like this:
define companyIds = 1,2,3
select * from PeopleInCompanies(companyIds)
is it even possible?
You would need to use a table type parameter. Assuming that CompanyID is an int:
CREATE TYPE dbo.ints AS TABLE ([value] int);
GO
CREATE FUNCTION dbo.PeopleInCompanies (#CompanyID dbo.ints READONLY)
RETURNS TABLE
AS RETURN
SELECT P.* --This should be replaced by the columns you need.
FROM dbo.Person P
JOIN #CompanyID CI ON P.CompanyID = CI.[Value];
Then you would call the function using:
DECLARE #CompanyID dbo.ints;
INSERT INTO #CompanyID
VALUES (1),(2),(3);
SELECT *
FROM dbo.PeopleInCompanies(#CompanyID);
SQL Server does not support macro substitution. That said, you have the table type as Gordon and Larnu mentioned, or you can simply parse/split the delimited string
Just another option
Declare #companyIds varchar(max) = '1,2,3'
Select A.*
From Person A
Join string_split(#companyIds,',') B
on A.CompanyID = B.Value

Combine sp result in select as column

I am trying to execute sp as sub query and treat result set of sp as column of outer query . Some thing like this
Select U.FirstName , (exec SomeSP ) as columnFromSP from User U
Is this possible i searched alot but found nothing on google.
Update
I cannot use #temp table because i am trying to do without #temp table
If you are able to convert your USP to a table value UDF, you will be use the UDF in your FROM statement.
CREATE FUNCTION dbo.SomeUDF
(
-- Add the parameters for the function here
#param varchar(1000)
)
RETURNS TABLE
AS
RETURN
(
SELECT #param as Value
)
GO
SELECT
a.Value,
'B' as Value2
FROM dbo.SomeUDF('ABC') a
Not possible, but you can work around it
Create a temp table & insert the results of the procedure into
it
Now join the User table with the temporary table and select the
columns you want from both tables
This assumes however, you have a joinable expression returned from the stored proc (one that you can match to a field in the user table). If the stored procedure on returns a single row, use a condition of 1=1 or something similar
-- Declare a temp table and column(for eg you have only 1 column)
CREATE TABLE #TEMP
(
FirstName VARCHAR(50)
)
-- The results after execution will be inserted to this table
INSERT INTO #TEMP
Exec SomeSP 'Params'
-- Select records from both tables in all combinations
SELECT U.FirstName , COL1 as columnFromSP
from User U
CROSS JOIN #TEMP

How do I define a stored procedure that returns table?

For example I have this stored procedure:
create procedure MyStoredProcedure
as
begin
select *
from X,Y
where x.Id = Y.ID
end
return #table table(X.tTitle, Y.Description)
I want return table and when use table in another query
Stored procedures cannot1 be composed into other queries as a source of rows - is there a reason why it has to be a stored procedure? A user defined function has almost the same amount of expressability as a stored procedure and can easily be a source of rows in the FROM clause of another query.
Something like:
create function MyFunction()
returns table
as
return (select X.tTitle,Y.Description
from X
inner join Y
on x.Id = Y.ID)
1 Ignoring INSERT...EXEC since it does nothing for composition, and OPENROWSET isn't always a viable approach.
Try this:
create procedure MyStoredProcedure
as
begin
select X.*,Y.*
From X INNER JOIN Y ON X.Id=Y.ID
end
This will select all data from tables X and Y.
Try This Way:
CREATE PROCEDURE [dbo].[MyStoredProcedure]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #ID int
set #ID =(select ID From X INNER JOIN Y ON X.Id=Y.ID)
IF #ID > 0
BEGIN
return #table table(X.tTitle,Y.Description)
END
END
you can simply Create a Procedure and then, Try this:
CREATE PROCEDURE MyStoredProcedure
AS
BEGIN
SELECT tTitle ,
Description
FROM X
JOIN Y ON Y.ID = X.ID
END
You can use temp tables or table variables.
Like this:
CREATE TABLE #TABLE
(
COLUMN DEFINITION
)
INSERT INTO #TABLE
EXEC <YOUR STORED PROCEDURE>
SELECT *
FROM #TABLE
DROP TABLE #TABLE
You can insert your stored procedure inside the temp table so you can use it as well as a table.
Note that temp table names should start with #.
Somethings like this you most write
CREATE PROCEDURE <SP_Name>
AS
BEGIN
Select ......
End

IF condition in view in SQL Server

Is it possible to have a if condition in VIEWS
eg
CREATE VIEW
as
DECLARE #Count int
SET #Count=-1
select #Count=EmpID from EmployeeDetails where ID=200
IF #Count=-1
BEGIN
SELECT * FROM TEAM1
END
ELSE
BEGIN
SELECT * FROM TEAM1
END
You could try something sneaky with a UNION :
SELECT {fieldlist}
FROM Table1
WHERE EXISTS(SELECT EmpID FROM EmployeeDetails WHERE ID = 200)
UNION ALL
SELECT {fieldlist}
FROM Table2
WHERE NOT EXISTS(SELECT EmpID FROM EmployeeDetails WHERE ID = 200)
This method would require both SELECT statements to return the same set of fields, although their sources might be different.
Views only allow select statements as stated in here
if you need to do if on column values you can use a
SELECT
CASE WHEN COLUMN1 = 1 THEN COLUMNX ELSE COLUMNY END
FROM TABLE1
if your need exceeds this you should create a select from a table valued function instead of a view.
What you need is a simple Procedure
CREATE PROCEDURE DOSOMETHING
(
#ID INT
)
AS
BEGIN
IF #ID > 100
SELECT 1 AS ID,'ME' AS NAME, GETDATE() AS VARIABLEDATECOL, NEWID() AS VARIABLEGUID
ELSE
SELECT 2 AS ID, 'YOU' AS NAME
END
No I don't believe this is possible.
You could use a stored procedure instead to achieve this functionality.
simply use a udf (User defined Function)
Here you can use IF, ELSE, WHILE etc.
But when you are manipulating data (INSERT, UPDATE, DELETE) then you have to use Stored Procedures because udf's aren't able to do that