Dynamically Select from different DB's based on input to sproc - sql

I'm trying to alter a stored procedure in our DB from a hard-coded select from 1 specific DB to be able to select from any of our DB's based on an id that's passed into the sproc. Here's the stub of what the sproc is doing for us:
ALTER PROCEDURE [dbo].[GetByAdId]
(
#AdId int,
#UserCompanyId int
)
AS
SET NOCOUNT ON
SELECT
[User].[UserId],
UserMappings.IsActive,
IsAccountOwner = ( SELECT Count(*) FROM DB1_SetUp.dbo.ad Adv WHERE Adv.AdID = UserMappings.AdID AND Adv.PrimaryAccountOwnerID = [User].[UserId] )
FROM
[User] INNER JOIN UserMappings ON
(
UserMappings.UserID = [User].UserID
AND UserMappings.AdID = #AdId
AND UserMappings.UserCompanyId = #UserCompanyId
)
Basically the "IsAccountOwner" variable is hardcoded to select from DB1_SetUp every time, but we have a number of SetUp db's for different groups, so like DB2_SetUp, DB3_SetUp, etc. The UserCompanyId variable being passed into the sproc functions like a group Id and can be used to point to the particular SetUp DB I want it to select from, but I'm not sure how to do this. I basically wanted something on the ilk of:
SELECT * FROM (
CASE #UserCompanyId
WHEN 3 THEN 'DB3_SetUp'
WHEN 4 THEN 'DB4_SetUp'
)
Is there a clean way to do this, or will I have to setup this sproc on each group DB and call the specific one over on each DB?

I've done this in the past by dynamically building the SQL I wanted to execute (based on parameters passed in) and then executing the SQL using sp_executesql
see: http://msdn.microsoft.com/en-us/library/ms188001.aspx

Related

How to create a reference value in Oracle SQl Developer

I use basic sql querying for my day to day work, but I regularly find myself needing to run queries in different tables using the same where clauses.
What I would ideally like to do is locally set a value to a name, for example:
traderef = ABCD1234. It's kind of like Defining a name in excel.
and then use 'traderef' in my queries,
select * from table1 where tranid = traderef
select * from table2 where tranid = traderef and otherattr = 'xyz1'
I only have query access to the dbs that i use, i have tried to google results, and found some info re SET
TIA
Declare a bind variable using the SQL/Plus and SQL Developer command VARIABLE name data_type and assign it a value using EXECUTE (or a PL/SQL anonymous block) and then use it in your queries:
VARIABLE traderef VARCHAR2(20)
EXEC :traderef := 'ABCD1234';
SELECT * FROM table1 WHERE tranid = :traderef;
SELECT * FROM table2 HWERE tranid = :traderef AND otherattr = 'xyz1';

Call a stored procedure from a select statement in a stored procedure

I have a SQL Server 2016 database with a table that stores an XML file. What I want to do if possible is to call another stored procedure and pass in the ApplicationID value.
My code is
select
RecID,
nref.value('APPLICATION_ID[1]','varchar(max)') ApplicationID ,
nref.value('FY[1]','varchar(max)') FY
into
ADMIN_stagingTable
from
[ADMIN_Grant_Exporter_Files_XML]
cross apply
XMLData.nodes('PROJECTS[1]/row[1]') as R(nref)
where
nref.value('ORG_DUNS[1]', 'varchar(max)') = '183710748'
I'm currently storing it into a staging table. Is there a better way than looping the result set?
SELECT #APPLICATION_ID = ApplicationID
FROM ADMIN_stagingTable
EXECUTE [Parse_Exporter] #APPLICATION_ID
try using function.
you can put the script of the SP in a function and then you can call it
name the function fn_Parse_Exporter
and use like this
SELECT *, dbo.fn_Parse_Exporter(ApplicationID)
FROM My_Table

Store a database name in variable & then using it dynamically

I have a Table in my Database Which have name of all the Database of my Server
Table Look like
create Table #db_name_list(Did INT IDENTITY(1,1), DNAME NVARCHAR(100))
INSERT INTO #db_name_list
SELECT 'db_One ' UNION ALL
SELECT 'db_Two' UNION ALL
SELECT 'db_Three' UNION ALL
SELECT 'db_four' UNION ALL
SELECT 'db_five'
select * from #db_name_list
I have so many SP in my Database..Which uses multiple table and Join Them..
At Present I am using the SQL code like
Select Column from db_One..Table1
Left outer join db_two..Table2
on ....some Condition ....
REQUIREMENT
But I do not want to HARDCODE the DATABASE Name ..
I want store DataBase name in Variable and use that .
Reason :: I want to restore same Database with Different name and want to Run those SP..At Present we Cant Do ,Because I have used db_One..Table1
or db_two..Table2
I want some thing like ...
/SAMPLE SP/
CREATE PROCEDURE LOAD_DATA
AS
BEGIN
DECLARE #dbname nvarchar(500)
set #dbname=( SELECT DNAME FROM #db_name_list WHERE Did=1)
set #dbname2=( SELECT DNAME FROM #db_name_list WHERE Did=2)
PRINT #DBNAME
SELECT * FROM #dbname..table1
/* or */
SELECT * FROM #dbname2.dbo.table1
END
i.e using Variable Instead of Database name ..
But it thow error
"Incorrect syntax near '.'."
P.S This was posted by some else on msdn but the answer there was not clear & I had the same kind of doubt. So please help
You can't use a variable like this in a static sql query. You have to use the variable in dynamic sql instead, in order to build the query you want to execute, like:
DECLARE #sql nvarchar(500) = 'SELECT * FROM ' + #dbname + '.dbo.mytable'
EXEC(#sql);
There seem to be a couple of options for you depending on your circumstances.
1. Simple - Generalise your procedures
Simply take out the database references in your stored procedure, as there is no need to have an explicit reference to the database if it is running against the database it is stored in. Your select queries will look like:
SELECT * from schema.table WHERE x = y
Rather than
SELECT * from database.schema.table WHERE x = y
Then just create the stored procedure in the new database and away you go. Simply connect to the new database and run the SP. This method would also allow you to promote the procedure to being a system stored procedure, which would mean they were automatically available in every database without having to run CREATE beforehand. For more details, see this article.
2. Moderate - Dynamic SQL
Change your stored procedure to take a database name as a parameter, such as this example:
CREATE PROCEDURE example (#DatabaseName VARCHAR(200))
AS
BEGIN
DECLARE #SQL VARCHAR(MAX) = 'SELECT * FROM ['+#DatabaseName+'].schema.table WHERE x = y'
EXEC (#SQL)
END

Parameterized WHERE clause in SQL Server Stored Procedure

I have a Stored Procedure to get the details of Invoices
Some occasions I get the list of invoices by sending only the InvoiceID
But in some other occasions I need to get the list of invoices as per the search fields supplied by the user. To do this I send all the fields to the Stored Procedure and use those parameters as below. I included only 2 columns but there are more.
SELECT * FROM INVOICES I
WHERE
(#InvoiceNumber is null or I.InvoiceNumber = #InvoiceNumber)
and
(#PONo is null or I.PONo = #PONo)
Is there a way to send the condition for the WHERE clause as one parameter?
Yes, it is possible with Dynamic SQL, but I highly discourage to do that.
SELECT * FROM tbl WHERE #condition:
If you are considering to write the procedure
CREATE PROCEDURE search_sp #condition varchar(8000) AS
SELECT * FROM tbl WHERE #condition
Just forget it. If you are doing this, you have not completed the transition to use stored procedure and you are still assembling your
SQL code in the client.
It will also open your application to SQL Injection attacks.
You can use custom type to pass table as parameter https://msdn.microsoft.com/pl-pl/library/bb510489(v=sql.110).aspx or you can use default parameters
If you're using SQL Server 2016 or similar (check by calling select compatibility_level, name from sys.databases and seeing that your DB is 130 or higher) then you can use the string_split builtin function.
I found it works best like this (spread out for clarity)
CREATE PROCEDURE [dbo].[GetInvoices]
#InvoiceNumber int = NULL
#PONo nvarchar(1024) = NULL
AS
SELECT * from [Invoices] AS [i]
WHERE
i.InvoiceNumber = ISNULL(#InvoiceNunber, i.InvoiceNunber)
AND CASE
WHEN #PONo is null
THEN 1
ELSE (CASE
WHEN i.PONo IN (select value from string_split(#PONo, ','))
THEN 1
ELSE 0
END)
END
= 1
So if you pass in a null to either parameter it gets translated as where x = x which is always true, and if you pass in a CSV value, it selects it from a split table of values that, if present, results in the where clause being where 1=1, which is true or 0=1 if the value is not present in the input list.
So here you can pass in an invoice number, or PO number, or both, or neither and it should return what you expect.

Sql Server make stored proc show select and run other proc on select's results

I need to make a stored procedure that will be called form a web method. The basic idea is the proc needs to
Check if there will be a result to the query (IF EXISTS ...)
If there is a result, return one row with an ID value the webmethod
will use
Call another stored proc using that same ID as a
parameter (this proc will then update the record the first proc took
the ID from and increase the value of one of it's column's).
So far I have
CREATE PROC Sponsors.GetLightBoxAds (#SponsorID varchar(30))
AS
BEGIN
IF EXISTS (SELECT TOP 1
AD.ADID
FROM Sponsors.AD
WHERE AD.Active = 1 and AD.Sponsor = #SponsorID)
--takes the ID value of first active AD record it finds, at random, for that sponsor
BEGIN
SELECT TOP 1
AD.ADID --I want to use this value as my parameter for the second proc.
FROM Sponsors.AD
WHERE AD.Active = 1
ORDER BY newid()
--Ideally I'd like to call a separate proc here because there's more to be done
--but for testing I'm trying to run the update here
UPDATE Sponsor.AD
SET AD.CurrentClickCount = AD.CurrentClickCount + 1
WHERE ADID = #ADID -- use the result of the first select here.
END
END
GO
Is there a way to make the proc both return the ID I wanted and call another proc using that ID as the call's parameter?
I could split this into separate calls and let the web backend handle the parameter calls but this adds latency and there are possible concurrency issues if this latency becomes large so I prefer to have the server run both calls asap.
As stated above, you would first need to declare #ADID - something like:
DECLARE #ADID INT;
Once you've done that, select the ID you want into it:
SELECT TOP 1 #ADID = AD.ADID
FROM Sponsors.AD
WHERE AD.Active = 1 and AD.Sponsor = #SponsorID
Then you can conditionally start your process:
IF ISNULL(#ADID,-1) != -1
BEGIN
EXEC YourStoredProc #ADID
END
To return the ID at the end, just do:
SELECT #ADID AS ADID;
You could instead use the output parameter method by declaring the output variable with your procedure:
CREATE PROC Sponsors.GetLightBoxAds (
#SponsorID varchar(30),
#ADIDOut INT OUTPUT
)
AS --...
Then do:
SELECT #ADIDOut = #ADID;