How to check temp table exists while Union multiple temp tables? - sql-server-2005

here my query-
SELECT final.* into #FinalTemp from
(
select * from #temp1
UNION
select * from #temp2
UNION
select * from #temp3
UNION
select * from #temp4
)final
but at a time only one temp table exists so how to check if #temp exists then do union or ignore?

You can't have a union or query on a non-existent object at compile time (compiling to a query plan just before execution).
So there is no way to refer to a non-existent table in the same batch
The pattern you have to use is like this: dynamic SQL is a separate batch
IF OBJECT('tempdb..#temp1') IS NOT NULL
EXEC ('SELECT * FROM #temp1')
ELSE IF OBJECT('tempdb..#temp3') IS NOT NULL
EXEC ('SELECT * FROM #temp3')
ELSE IF OBJECT('tempdb..#temp3') IS NOT NULL
EXEC ('SELECT * FROM #temp3')
...

Would you not be better creating #FinalTemp as an explicit temp table at the top of your query, and then replace your existing population methods which I assume look like this:
SELECT * INTO #temp1 FROM ... /* Rest of Query */
With:
INSERT INTO #FinalTemp (Columns...)
SELECT * FROM ... /* Rest of Query */
And then you don't have to do this final union step at all. Or, if you do need 4 separate temp tables (perhaps for multi-step operations on each), define each of them at the start of your query, and then they will all exist when you perform the union.
Now, given you've said only one will be populated (so the others will be empty), it's probably moot, but I always tend to use UNION ALL to combine disjoint tables - unless you're implicitly relying on UNIONs duplicate removal feature?
You can declare Temp Tables using the same syntax as you do for real tables:
CREATE TABLE #FinalTemp (
ColumnA int not null primary key,
ColumnB varchar(20) not null,
ColumnC decimal(19,5) null,
)
Or, as you've also alluded to, you can use table variables rather than temp tables:
declare #FinalTemp table (
ColumnA int not null primary key,
ColumnB varchar(20) not null,
ColumnC decimal(19,5) null,
)
The predominant different (so far as I'm concerned) is that table variables follow the same scoping rules as other variables - they're not available inside a called stored procedure, and they're cleaned up between batches.

Related

T-SQL function that returns a table data type. Wanting to traverse this table

This article returns all lines of an input file (.txt, .csv, etc.) but puts it into a table. I have this code:
SELECT
*
INTO
#MyTemp
FROM
Dbo.uftReadfileAsTable('C:\test','test.txt.txt')
But isn't there an opportunity for efficiency here? Dbo.uftReadfileAsTable('C:\test','test.txt.txt') returns a table, but it has no name assigned for me to work with. I'm dreaming this up in my head, but I don't know the right syntax to handle this in the most efficient way:
Declare #T Table
Set #T = Dbo.uftReadfileAsTable('C:\test','test.txt.txt')
I know this is wrong. Just trying to see if I can do what I need in an efficient way. I can do anything I want with #myTemp to process it. For example, I want to do something like this, but in a loop:
Declare #Line varchar(Max)
SELECT
#Line = Line from #MyTemp
WHERE
[LineNo] = 1
--do something here with line...
DELETE FROM
#MyTemp
WHERE
[LineNo] = 1
The closest analog to what you're suggesting would be to declare a temporary table and INSERT into it from the tvf. Alternately, for a single query you could use a CTE as per Aaron Bertrand's comment.
/* declare temporary table */
declare
#t table(ColumnA int unique not null,
ColumnB Varchar(30) not null,
ColumnC Varchar(30) null);
/* insert into temporary table */
insert #t(ColumnA, ColumnB, ColumnC)
select * from Dbo.uftReadfileAsTable('C:\test','test.txt.txt');
/* returns rows temp table which were inserted from the tvf */
select * from #t;
/* single query CTE */
with csv_cte as (
select * from Dbo.uftReadfileAsTable('C:\test','test.txt.txt'))
select cc.*
from csv_cte cc;

Select View dynamically in sql

may anyone please share your expertise .
i have a table contain customerid and it has only 1 specific value at a given time.
DDL Table:
CREATE TABLE CUSTOMER
(
[CUSTOMERID] [int] NOT NULL
)
INSERT CUSTOMER
SELECT 100 UNION
SELECT 105 UNION
SELECT 108
here in example i have showed 3 value, but in table there will be always 1 value at given time.
and before loading other value, first value will get deleted.
now i have 60 views created for 60 different customer. each customer has different data pattern and logic associated with it.
example of views. Note: This is just example and not actual logic
CREATE VIEW V1
as
(
select * from dwhtable
where colummnx = '100'
)
similarly
CREATE VIEW V2
as
(
select * from dwhtable
where columnx = '105
)
Mapping Table
create table mapping_table
(
custID int,
view_name varchar (150)
)
insert mapping_table
select 100, 'v1' union all
select 105, 'v2' union all
select 108, 'v3'
i am trying to automate the entire process either by SP or Function or DynamicSQL.
So my views will run for a specific customer.
Now How do we know which view goes with which customer.
The customer table will come in picture, and we need to match the value in customer table and which view contain that value.
i am not sure whether it is achievable in sql.
Please share your expertise.
Thanks
Not sure if I understand the task correctly. So the requirement is to have one view per customer. We need to get all the columns from that view for a given customer.
So you need to have a mapping table Customer_View_Mapping (customer_id int, view_name varchar(128))
Then you can get the name of view:
declare #name varchar(128)
select #name = view_name from Customer_View_Mapping where customer_id = #customer_id
the you can execute something like this:
EXEC (N'select * from ' + #name)
You can insert the results to the temp table if required.
INSERT INTO #table (<column list>)
EXEC (N'select * from ' + #name)

Optimizing deletes from table using UDT (tsql)

SQL Server.
I have a proc that takes a user defined table (readonly) and is about 7500 records large. Using that UDT, I run about 15 different delete statements:
delete from table1
where id in (select id from #table)
delete from table2
where id in (select id from #table)
delete from table3
where id in (select id from #table)
delete from table4
where id in (select id from #table)
....
This operation, as expected, does take a while (about 7-10 minutes). These columns are indexed. However, I suspect there is a more efficient way to do this. I know deletes are traditionally slower, but I wasn't expecting this slow.
Is there a better way to do this?
You can test/try "exists" instead of "IN". I really don't like IN clauses for anything besides casual lookup-queries. (Some people will argue about IN until they are blue in the face)
Delete deleteAlias
from table1 deleteAlias
where exists ( select null from #table vart where vart.Id = deleteAlias.Id )
You can populate a #temp table instead of a #variableTable. Again, over the years, this has been trial and test it out. #variable vs #temp , most of the time, doesn't make that big of a different. But in about 4 situations I had, going to a #temp table made a big impact.
You can also experiment with putting an index on the #temp table (the "joining" column, 'Id' in this example )
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
CREATE TABLE #Holder
(ID INT )
/* simulate your insert */
INSERT INTO #HOLDER (ID)
select 1 union all select 2 union all select 3 union all select 4
/* CREATE CLUSTERED INDEX IDX_TempHolder_ID ON #Holder (ID) */
/* optional, create an index on the "join" column of the #temp table */
CREATE INDEX IDX_TempHolder_ID ON #Holder (ID)
Delete deleteAlias
from table1 deleteAlias
where exists ( select null from #Holder holder where holder.Id = deleteAlias.Id )
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
IMHO, there is not clear cut answer, sometimes you gotta experiment a little.
And "how your tempdb is setup' is a huge fork in the road that can affect #temp table performance. But try the suggestions above first.
And one last experiment
Delete deleteAlias
from table1 deleteAlias
where exists ( select 1 from #table vart where vart.Id = deleteAlias.Id )
change the null to "1".... once I saw this affect something. Weird, right?

How best to call a dynamic table

I have a script which is quite a beefy select statement and the format of it is as below.
It works perfectly well as a standalone script, but the local variable and temporary table restrictions in functions and views are preventing me from adding it to a database. What is the best way of creating this dynamic data which I can call in the FROM clause of a stored procedure without using functionality that was not available prior to SQL2005?
CREATE TABLE t1
(CARE_ID int NOT NULL,EVENT_DATE datetime NULL,EVENT_ID int NULL,EVENT_TYPE varchar(20))
CREATE TABLE t2
(CARE_ID int NOT NULL,EVENT_DATE datetime NULL,EVENT_ID int NULL,EVENT_TYPE varchar(20))
INSERT INTO t1
SELECT STATEMENT GOES HERE
INSERT INTO t2
SELECT STATEMENT GOES HERE
SELECT * FROM anotherTable
UNION
SELECT * FROM t1
UNION
SELECT * FROM t2
DROP TABLE t1
DROP TABLE t2
Microsoft introduced table variables with SQL Server 2000 as an alternative to using temporary tables.
DECLARE #T1 TABLE
(
CARE_ID int NOT NULL,
EVENT_DATE datetime NULL,
EVENT_ID int NULL,
EVENT_TYPE varchar(20)
)
INSERT INTO #T1
SELECT STATEMENT GOES HERE
These are perfectly suitable for use within a stored procedure.

How can I create two temporary tables with the same structure without write twice?

How can I create two temporary tables with the same structure without write twice?
Something like that:
DECLARE #TEST_TABLE1, #TEST_TABLE2 TABLE
(
FIELD1 INT,
FIELD2 INT
)
and NO:
DECLARE #TEST_TABLE1 TABLE
(
FIELD1 INT,
FIELD2 INT
)
DECLARE #TEST_TABLE2 TABLE
(
FIELD1 INT,
FIELD2 INT
)
These are not "temp tables", a temp table is CREATE TABLE #TempTable(x int)
to make this work for true table tables, try:
CREATE TABLE #TempTable(x int)
insert into #TempTable values(5) --test data to show no data copied to new table
select * into #tempTable2 from #TempTable where 1=2
select * from #TempTable
select * from #TempTable2
These are table vaiables (#tableVariable) and you have to declare each variable, there is no way around it.
The only very non-standard way I can think this may work is to just write to the sys.tables directly, but you would still have to do two inserts, but you are doing the tables at the same time.
That may not be what you want, but short of using a stored procedure, and making one call from your app, and two on the database I can't think of any other solution.
Create the first temp table, then select into a second temp table:
-- Create first temp table
CREATE TABLE #TEST_TABLE1
(
FIELD1 int
,FIELD2 int
)
-- Select into second temp table
SELECT *
INTO #TEST_TABLE2
FROM #TEST_TABLE1
-- Vet existence of both temp tables
SELECT * FROM #TEST_TABLE1
SELECT * FROM #TEST_TABLE2