sql issue with declare query - sql

I've got a java application that I'm using to retrieve information from a table in sql.
The problem is that the tables change depending on the main application that is using them; there is a view that has all of the active information from the active table eg table_all which is fine, what i want to do is search for a particular number in table that was a part of the view
DECLARE #iss int, #act_tb char(1)
SET #iss = (select cust_nr from table_all where num = '123456789')
SET #act_tb = (select curr_table_active from pc_group where cust_nr = #iss)
select * from pc_grp_#iss_#act_tb
so what i would now want to do is update a field in pc_grp_#iss_#act_tbenter code here format is pc_grp_<#iss>_<#act_tb>.
is there any way i can do that as pc_grp_#iss_#act_tb is picked up as a table and not a variable table name.
Many thanks

i think you are looking for this-:
Declare #query as varchar(Max);
Set #query='Select * from select * from pc_grp_'+Cast(#iss as varchar)+'_'+Cast(#act_tb as varchar) ;
Exec(#query)

Related

How to find related table/view name to use for from statement by using a value in SQL Server

I have a table X in SQL Server which includes a column called Type varchar(10) with 15 potential values: AAA, BBB1, BBB2, CCC, ..., and another column called IfExists bit.
In the same DB, I have 15 different views, a view for each Type, including X_ID as well. Examples of view names:
View_ReportingAAA
View_ReportingBBB1
View_ReportingBBB2
View_ReportingCCC
....
Usually what I do is to see the Type of the record by using its X_ID provided to me in Table X and use a select query to the related view to get some data.
What I need to do is now to create a trigger for Table X to set 1 for the value of IfExists field if there is a record in the related view for the record id X_ID.
My question is: What is the best way to find and use the related view name for this purpose by using a value of a field in the main table?
I am using the code below for this, but I am not sure if it is the most efficient way to handle this. Any help or advice would be appreciated.
declare #ifExists int = 0;
declare #sql nvarchar(max) = 'set #ifExists = (Select count(*) from View_Reporting';
declare #tablename nvarchar(max) = (Select Type from X where X_ID = #X_ID)
set #sql = #sql + #tablename + ' where V_xid = #X_ID)';
EXECUTE sp_executesql #sql
if (#ifExists > 0)
begin
update X set IfExists = 1 where X_ID = #X_ID
end
Maybe this could be easier:
declare #ifExists bit
select #ifExists=count(*) from INFORMATION_SCHEMA.VIEWS
where TABLE_NAME='View_Reporting'+(select [Type] from X where X_ID=#X_ID)
update X set IfExists=#IfExists where X_ID=#X_ID and IfExists<>#IfExists

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

dynamic sql not working . Regular sql working [duplicate]

It looks like #temptables created using dynamic SQL via the EXECUTE string method have a different scope and can't be referenced by "fixed" SQLs in the same stored procedure.
However, I can reference a temp table created by a dynamic SQL statement in a subsequence dynamic SQL but it seems that a stored procedure does not return a query result to a calling client unless the SQL is fixed.
A simple 2 table scenario:
I have 2 tables. Let's call them Orders and Items. Order has a Primary key of OrderId and Items has a Primary Key of ItemId. Items.OrderId is the foreign key to identify the parent Order. An Order can have 1 to n Items.
I want to be able to provide a very flexible "query builder" type interface to the user to allow the user to select what Items he want to see. The filter criteria can be based on fields from the Items table and/or from the parent Order table. If an Item meets the filter condition including and condition on the parent Order if one exists, the Item should be return in the query as well as the parent Order.
Usually, I suppose, most people would construct a join between the Item table and the parent Order tables. I would like to perform 2 separate queries instead. One to return all of the qualifying Items and the other to return all of the distinct parent Orders. The reason is two fold and you may or may not agree.
The first reason is that I need to query all of the columns in the parent Order table and if I did a single query to join the Orders table to the Items table, I would be repoeating the Order information multiple times. Since there are typically a large number of items per Order, I'd like to avoid this because it would result in much more data being transfered to a fat client. Instead, as mentioned, I would like to return the two tables individually in a dataset and use the two tables within to populate a custom Order and child Items client objects. (I don't know enough about LINQ or Entity Framework yet. I build my objects by hand). The second reason I would like to return two tables instead of one is because I already have another procedure that returns all of the Items for a given OrderId along with the parent Order and I would like to use the same 2-table approach so that I could reuse the client code to populate my custom Order and Client objects from the 2 datatables returned.
What I was hoping to do was this:
Construct a dynamic SQL string on the Client which joins the orders table to the Items table and filters appropriate on each table as specified by the custom filter created on the Winform fat-client app. The SQL build on the client would have looked something like this:
TempSQL = "
INSERT INTO #ItemsToQuery
OrderId, ItemsId
FROM
Orders, Items
WHERE
Orders.OrderID = Items.OrderId AND
/* Some unpredictable Order filters go here */
AND
/* Some unpredictable Items filters go here */
"
Then, I would call a stored procedure,
CREATE PROCEDURE GetItemsAndOrders(#tempSql as text)
Execute (#tempSQL) --to create the #ItemsToQuery table
SELECT * FROM Items WHERE Items.ItemId IN (SELECT ItemId FROM #ItemsToQuery)
SELECT * FROM Orders WHERE Orders.OrderId IN (SELECT DISTINCT OrderId FROM #ItemsToQuery)
The problem with this approach is that #ItemsToQuery table, since it was created by dynamic SQL, is inaccessible from the following 2 static SQLs and if I change the static SQLs to dynamic, no results are passed back to the fat client.
3 around come to mind but I'm look for a better one:
1) The first SQL could be performed by executing the dynamically constructed SQL from the client. The results could then be passed as a table to a modified version of the above stored procedure. I am familiar with passing table data as XML. If I did this, the stored proc could then insert the data into a temporary table using a static SQL that, because it was created by dynamic SQL, could then be queried without issue. (I could also investigate into passing the new Table type param instead of XML.) However, I would like to avoid passing up potentially large lists to a stored procedure.
2) I could perform all the queries from the client.
The first would be something like this:
SELECT Items.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
SELECT Orders.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
This still provides me with the ability to reuse my client sided object-population code because the Orders and Items continue to be returned in two different tables.
I have a feeling to, that I might have some options using a Table data type within my stored proc, but that is also new to me and I would appreciate a little bit of spoon feeding on that one.
If you even scanned this far in what I wrote, I am surprised, but if so, I woul dappreciate any of your thoughts on how to accomplish this best.
You first need to create your table first then it will be available in the dynamic SQL.
This works:
CREATE TABLE #temp3 (id INT)
EXEC ('insert #temp3 values(1)')
SELECT *
FROM #temp3
This will not work:
EXEC (
'create table #temp2 (id int)
insert #temp2 values(1)'
)
SELECT *
FROM #temp2
In other words:
Create temp table
Execute proc
Select from temp table
Here is complete example:
CREATE PROC prTest2 #var VARCHAR(100)
AS
EXEC (#var)
GO
CREATE TABLE #temp (id INT)
EXEC prTest2 'insert #temp values(1)'
SELECT *
FROM #temp
1st Method - Enclose multiple statements in the same Dynamic SQL Call:
DECLARE #DynamicQuery NVARCHAR(MAX)
SET #DynamicQuery = 'Select * into #temp from (select * from tablename) alias
select * from #temp
drop table #temp'
EXEC sp_executesql #DynamicQuery
2nd Method - Use Global Temp Table:
(Careful, you need to take extra care of global variable.)
IF OBJECT_ID('tempdb..##temp2') IS NULL
BEGIN
EXEC (
'create table ##temp2 (id int)
insert ##temp2 values(1)'
)
SELECT *
FROM ##temp2
END
Don't forget to delete ##temp2 object manually once your done with it:
IF (OBJECT_ID('tempdb..##temp2') IS NOT NULL)
BEGIN
DROP Table ##temp2
END
Note: Don't use this method 2 if you don't know the full structure on database.
I had the same issue that #Muflix mentioned. When you don't know the columns being returned, or they are being generated dynamically, what I've done is create a global table with a unique id, then delete it when I'm done with it, this looks something like what's shown below:
DECLARE #DynamicSQL NVARCHAR(MAX)
DECLARE #DynamicTable VARCHAR(255) = 'DynamicTempTable_' + CONVERT(VARCHAR(36), NEWID())
DECLARE #DynamicColumns NVARCHAR(MAX)
--Get "#DynamicColumns", example: SET #DynamicColumns = '[Column1], [Column2]'
SET #DynamicSQL = 'SELECT ' + #DynamicColumns + ' INTO [##' + #DynamicTable + ']' +
' FROM [dbo].[TableXYZ]'
EXEC sp_executesql #DynamicSQL
SET #DynamicSQL = 'IF OBJECT_ID(''tempdb..##' + #DynamicTable + ''' , ''U'') IS NOT NULL ' +
' BEGIN DROP TABLE [##' + #DynamicTable + '] END'
EXEC sp_executesql #DynamicSQL
Certainly not the best solution, but this seems to work for me.
I would strongly suggest you have a read through http://www.sommarskog.se/arrays-in-sql-2005.html
Personally I like the approach of passing a comma delimited text list, then parsing it with text to table function and joining to it. The temp table approach can work if you create it first in the connection. But it feel a bit messier.
Result sets from dynamic SQL are returned to the client. I have done this quite a lot.
You're right about issues with sharing data through temp tables and variables and things like that between the SQL and the dynamic SQL it generates.
I think in trying to get your temp table working, you have probably got some things confused, because you can definitely get data from a SP which executes dynamic SQL:
USE SandBox
GO
CREATE PROCEDURE usp_DynTest(#table_type AS VARCHAR(255))
AS
BEGIN
DECLARE #sql AS VARCHAR(MAX) = 'SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''' + #table_type + ''''
EXEC (#sql)
END
GO
EXEC usp_DynTest 'BASE TABLE'
GO
EXEC usp_DynTest 'VIEW'
GO
DROP PROCEDURE usp_DynTest
GO
Also:
USE SandBox
GO
CREATE PROCEDURE usp_DynTest(#table_type AS VARCHAR(255))
AS
BEGIN
DECLARE #sql AS VARCHAR(MAX) = 'SELECT * INTO #temp FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''' + #table_type + '''; SELECT * FROM #temp;'
EXEC (#sql)
END
GO
EXEC usp_DynTest 'BASE TABLE'
GO
EXEC usp_DynTest 'VIEW'
GO
DROP PROCEDURE usp_DynTest
GO

How to get new column data from varchar column

I got help to get select query to get the correct data, but how can I insert this into table.
Following
Select RIGHT(RTRIM(Template_name), 2) country
from TABLE
This gets for me following:
Example data:
Template_name Country
Party_package_US US
PARTY_Package_GB GB
Random_temp_DE DE
But the main question is how can I insert into table where template_name exists and add only the country initials to new column.
Link for earlier question where I got help: how to get info from VARCHAR column and create new column out of it
I figured that I could do subselect that inserts right form to new column
UPDATE #silverpop_header
SET MARKET_AREA = a.template_name
FROM #silverpop_header pop
join dw.f_CRM a
ON pop.template_name = a.TEMPLATE_NAME
left join (
select
RIGHT(RTRIM(Template_name), 2) country
from dw.f_CRM )
But I think I have done this wrong somehow
But the main question is how can I insert into table where template_name exists and add only the country initials to new column.
Please find the below script to perform the operation based on your comment mentioned above :
update silverpop_header set MARKET_AREA = (Select RIGHT(RTRIM(Template_name), 2) country from silverpop_header a where a.TEMPLATE_NAME = 'Party_package_US');
This will update the record for Party_package_US template. If you want to perform for all the templates then you have to write a simple cursor to read all template_name and execute the same update query for each template.
Update me if anything is required.
Find the cursor below which has been written for SQLServer.
DECLARE #TAMPLATENAME VARCHAR(100), #SQL VARCHAR(500), #quotes varchar(4)
DECLARE UPDATE_COUNTRIES CURSOR FOR SELECT TEMPLATE_NAME FROM silverpop_header
set #quotes = '''';
OPEN UPDATE_COUNTRIES
FETCH NEXT FROM UPDATE_COUNTRIES INTO #TAMPLATENAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'update silverpop_header set MARKET_AREA = (Select RIGHT(RTRIM(Template_name), 2) country from silverpop_header a where a.TEMPLATE_NAME = '+#quotes+#TAMPLATENAME+#quotes+' ) where TEMPLATE_NAME = '+#quotes+#TAMPLATENAME+#quotes
print(#SQL)
EXEC(#SQL)
FETCH NEXT FROM UPDATE_COUNTRIES INTO #TAMPLATENAME
END
CLOSE UPDATE_COUNTRIES
DEALLOCATE UPDATE_COUNTRIES
The final result that worked is following:
update #temp_table
set veerg2 = RIGHT(RTRIM(nimi), 3)
from #temp_table a
where a.nimi is not NULL ;
Just cuting out select on the SET part did the trick

How do I declare strings of data

I have a long code that is creating financial accounting data.
The code uses multiple unions to breakout data to different company groupings.
There are 5-6 account groupings that are reference multiple times.
Anytime there is a change to the groupings I have to go through the code and change it in each location.
An example of the string is below:
Where account in ('81000', '82000','87000','83600','67000')
and account like '814%'
Is there anyway to put this in a declare or just internally link to that code in other where statements?
There are several ways to do what you describe, which is best will depend on your exact needs.
First and simplest is to use variables.
declare #account1 int; set #account1 = 81000;
declare #account2 int; set #account2 = 82000;
declare #account3 int; set #account3 = 87000; /* and so forth*/
It's not clear from your question whether this is being called from a front end app, if it is, you can use sql parameters to set the account values.
string cmd =' declare #account1 int; set #account1 = #acount1In;
select columnslist from accounts where account in (#account1)
union
select columnslist from accounts where account in (#account1)
';
Secondly, you could put the values either into a temporary table or table variable.
declare #accountIds table (account int);
insert into #accountIds values(81000);
select columnlist from accounts where account in (select account from #accounts);
Finally, if this is really the same expression done multiple times, you might consider using a common table expression.
;using cte as (select columnlist from accounts where account in (81000, 87000)
)
select columnlist from cte inner join table2 on a=b
union
select columnlist from cte inner join table3 on a=c