Having a same temp table name with 2 different IF statements - sql

I have resolved this problem because I have overlooked something that is already part of my code and this situation is not needed.
In SQL Server 2008, I have two IF statements
If value = ''
begin
select * into #temptable from table 1
end
Else If value <> ''
begin
select * into #temptable from table 2
end
but when I try to execute it gives me because of the second
temptable:
There is already an object named '#temptable' in the database.
I don't want to use another temp table name as I would have to change the after code a lot. Is there a way to bypass this?

I would recommend making some changes so that your code is a little more maintainable. One problem with the way you have it set up here is with the SELECT * syntax you're using. If you later decide to make a change to the schema of table1 or table2, you could have non-obvious consequences. In production code, it's better to spell these things out so that it's clear exactly which columns you're using and where.
Also, are you really using all of the columns from table 1 and table 2 in the code that follows? You might be taking a performance hit loading more data than you need. I'd go through the code that uses #temptable and figure out which columns it's actually using. Then start by creating your temp table:
CREATE TABLE #temptable(col1 int, col2 int, col3 int, col4 int)
Include all of the possible columns that could be used, even if some of them might be null in certain cases. Presumably, the code that follows already understands that. Then you can set up your IF statements:
IF value = ''
BEGIN
INSERT INTO #temptable(col1, col2, col3)
SELECT x,y,z
FROM table1
END
ELSE
INSERT INTO #temptable(col1, col4)
SELECT alpha,beta
FROM table2
END

Your SELECT statement, as written, is creating the temp table and INSERTING into it all in one statement. Create the temp table separately with a CREATE TABLE statement, then INSERT INTO in your two IF statements.

Using SELECT INTO creates the table on the fly, as you know. Even if your query only referenced #temptable once, if you were to run it more than once (without dropping the table after the first run), you would get the same error (although if it were inside a stored procedure, it would probably only exist in the scope of the stored procedure).
However, you can't even compile this query. Using the Parse command (Ctrl+F5) on the following query, for example, fails even though the same table is used as the source table.
select * into #temptable from SourceTable
select * into #temptable from SourceTable
If the structure of tables 1 and 2 were the same, you could do something like the following.
select * into #temptable from
(select * from Table1 where #value = ''
union
select * from Table2 where #value <> '') as T
If, however, the tables have different structures, then I'm not sure what you can do, other than what agt and D. Lambert recommended.

Related

Add data from one table into another with same column names

I have found numerous examples here, on YouTube, and in general Google searches but I'm still hitting a wall. I have two databases with (I believe) identical tables, structure, etc.
db1.dbo.table has a lot more information than does db2.dbo.table. I want to copy SOME of the information from db1.dbo.table into the already-created db2.dbo.table (which has some existing values I would like to keep).
Here's an example:
SELECT * FROM table WHERE TYPE = '1'
If I run that against db1.dbo.table, it returns a value of 12 rows. When run against db2.dbo.table, it ruturns 2 rows. I want to KEEP those two rows, but then add the other 12 rows from db1.dbo.table.
If I use:
select * into db2.dbo.table from db1.dbo.table
I get the error that the table already exists.
If I try the following:
Use db1
go
insert into table
select *
from table
where type (this is one of my column names) = '1' (one of the appropriate values)
I receive "An explicit value for the identity column in table 'table' can only be specified when a column list is used and IDENTITY_INSERT is ON." In researching that, I've tried the following:
Set Identity_Insert table (the name of my table) ON
Go
Insert into db2.dbo.table(column 1,column2,etc.,)
select (here, I've tried * as well as the same column1,column2,etc., values as above)
From db1.dbo.table
I've still not hit on the correct combination. I'd say I'm still a novice at SQL, but I understand technology and I comprehend what is happening in the examples I read/attempt to edit and execute for my environment, I'm just not sure of how to properly troubleshoot. I will restate below what I want to accomplish.
I want to copy values returned from:
SELECT * FROM TABLE WHERE TYPE = '1' in db1 (returns 12 rows)
into db2 (where the same returns 2 rows, I want this to return the same 2, plus the 12 from the other db when I'm done).
Instead of SELECT INTO, try to INSERT INTO:
INSERT INTO
db2.dbo.table
(
col1,
col2,
col3,
etc.
)
SELECT
col1,
col2,
col3,
etc.
FROM
db1.dbo.table
WHERE
TYPE = '1'

Create new temp table from old temp table using Create As Select

I am doing some testing and unable to create a new temp table from old temp table.
This is my code.
1st table
CREATE TABLE #Temp1 ( Col1 Money, Col2 Money );
This works fine.
2nd table
CREATE TABLE #Temp2
AS (Select Col1, Col2
From #Temp1)
This errors with
Incorrect syntax near '('.
I am following this link to learn, which has the following code
CREATE TABLE new_table
AS (SELECT * FROM old_table);
This is almost the same as mine, except mine are temp tables.
I tried using
CREATE TABLE #Temp2
AS (Select Col1, Col2
From tempdb..#Temp1)
to make sure it finds the path of the temp table
but it gives me
Database name 'tempdb' ignored, referencing object in tempdb.
Is there a different way to do it when both are temp tables ?
The CREATE AS syntax is not valid for SQL Server. That site doesn't say which RDMBS that is for so maybe it is more generic and works on others. Here is the MSDN page for CREATE TABLE.
Creating tables on the fly can be done with the INTO clause of a SELECT statement.
If you want to copy the table (schema and data):
SELECT *
INTO #Temp2
FROM #Temp1
If you only want to create a similar table (schema only):
SELECT *
INTO #Temp2
FROM #Temp1
WHERE 1 = 0;

Avoid code duplication in sql

I will preface this question by saying my sql is not very good :)
We are attempting to build a double buffered implementation in sql by having 2 redundant tables. At any one time 1 of the tables are active and the other inactive. The tables are accessed by a view which we toggle after reloading data. When we reload we want to perform operations on the inactive table and then toggle the active cache on completion.
We have lots of code that looks a bit like:
IF #activeCache = 0
BEGIN WORK ON TABLE 1 AS IT IS INACTIVE
ELSE
BEGIN WORK ON TABLE 0 AS IT IS INACTIVE
The problem is the code between the brackets is not trivial so we end up duplicating the code where the only difference is the table being operated on. We thought table parameters might help but you can't insert into them (which we need to do). My only idea now is to use T4 templates to generate the crud for us but I can't seem to get them to work in a database project.
Is there any sql constructs that can help us? We'd rather not use dynamic sql if possible.
You can use CREATE SYNONYM to effectively create a permanent alias (or "synonym", if you will) for an object. You can run your logic once to decide which table to target, and then run:
CREATE SYNONYM WorkingTable FOR Table1
CREATE SYNONYM MainTable FOR Table2
Then to switch:
DROP SYNONYM WorkingTable
DROP SYNONYM MainTable
CREATE SYNONYM WorkingTable FOR Table2
CREATE SYNONYM MainTable FOR Table1
And everywhere else in your scripts, you can just reference WorkingTable for updates, and MainTable for reads.
That being said, I agree with other comments/answers that question whether this is the best way of working.
Instead of using two tables and switching the view, use a main table and a staging table.
When you are ready to migrate the data to the main table, you can do it in an atomic transaction like so.
begin try
begin tran
delete * from MainTable with (tablockx)
insert MainTable
select * from StagingTable with (tablockx)
commit
end try
begin catch
rollback
raiserror('An error occurred swapping staging data', 16,16)
end catch
That way you always work on the staging table, so there is no difficulty identifying the correct table to use.
Depending on the data you may want to do an incremental update of the main table:
-- delete rows which no longer exist
delete MainTable
from MainTable
where not exists (select 1 from StagingTable where StagingTable.primaryKey = MainTable.primaryKey)
-- Insert new rows
insert MainTable
select *
from StagingTable
where not exists (select 1 from MainTable where StagingTable.primaryKey = MainTable.primaryKey)
-- update rows which have changed
update MainTable
set
col1 = stagingTable.col1,
col2 = stagingTable.col2
from MainTable inner join StagingTable on StagingTable.primaryKey = MainTable.primaryKey
where 1=2
-- Need to compare every column, only update if one is different
-- Both null counts as the same - compare nullity
OR case when MainTable.col1 is null then 0 else 1 end <> case when StagingTable.col1 is null then 0 else 1 end
OR MainTable.col1 <> StagingTable.col1
OR case when MainTable.col2 is null then 0 else 1 end <> case when StagingTable.col2 is null then 0 else 1 end
OR MainTable.col2 <> StagingTable.col2
You can create Inline Table-Valued function which takes #activeCache as a parameter. Select all data from proper table according to parameter in that function. TI'm not sure about performance.

SQL insert into using Union should add only distinct values

So I have this temp table that has structure like:
col1 col2 col3 col3
intID1 intID2 intID3 bitAdd
I am doing a union of the values of this temp table with a select query and storing
it into the same temp table.The thing is col3 is not part of the union query I will
need it later on to update the table.
So I am doing like so:
Insert into #temptable
(
intID1,
intID2,
intID3
)
select intID1,intID2,intID3
From
#temptable
UNION
select intID1,intID2,intID3
From
Table A
Issue is that I want only the rows that are not already existing in the temp table to be added.Doing it this way will add a duplicate of the already existing row(since union will return one row)How do I insert only those rows not existing in the current temp table in my union query?
Use MERGE:
MERGE INTO #temptable tmp
USING (select intID1,intID2,intID3 From Table A) t
ON (tmp.intID1 = t.intID1 and tmp.intID2 = t.intID2 and tmp.intID3 = t.intID3)
WHEN NOT MATCHED THEN
INSERT (intID1,intID2,intID3)
VALUES (t.intID1,t.intID2,t.intID3)
Nice and simple with EXCEPT
INSERT INTO #temptable (intID1, intID2, intID3)
SELECT intID1,intID2,intID3 FROM TableA
EXCEPT
SELECT intID1,intID2,intID3 FROM #temptable
I see where you are coming from. In most programming languages #temptable would be a variable (a relation variable or relvar for short) to which you would assign a value (a relation value) thus:
#temptable := #temptable UNION A
In the relational model, this would achieve the desired result because a relation has no duplicate rows by definition.
However, SQL is not truly relational and does not support assignment. Instead, you are required to add rows to a table using SQL DML INSERT statements (which is not so bad: the users of a truly relational database language, if we had one, would no doubt demand a similar shorthand for relational assignment!) but you are also required to do the test for duplicates yourself.
The answers from Daniel Hilgarth and Joachim Isaksson both look good. It's good practice to have two good, logically sound candidate answers then look for criteria (usually performance under typical load) to eliminate one (but retaining it commented out for future re-testing!)

How to create a stored procedure which pulls data from multiple tables that are not linked What do i do

I need to create a stored procedure which pulls data from multiple tables that are not linked what do i do .Basically i got a few tables that are not linked and all i need to do is pull all the data from all those tables.
PLEASE HELP MY LIFE DEPENDS ON THIS
Just do several selects?
select * from MyTable1;
select * from MyTable2;
select * from MyTable3;
You can then access each of those tables from your calling code. I'd include an example on how to do that, but you don't include any details about what language you are calling from.. details I would have included if my life depended on it :)
If you mean you have rows in several tables, and you want to pull them all back then you can do that by doing a UNION.
What do you mean by 'not linked'? Are they on the same sql server instance?
If so, just select from the full schema name.
Eg.
Select * from database1.dbo.table
Select * from database2.dbo.table
If you want a single result set you can use the JOIN keyword whether or not the tables have foreign key relationships defined; just specify which columns you would like to join the tables on.
Alternatively, you can use multiple result sets and just have multiple SELECT statements.
Your questions is not clear, but if you are trying to pull just certain things from certain tables and then return them to the user, can do something like this:
CREATE PROCEDURE spMyTestProc
AS
DECLARE #F1 int
DECLARE #F2 int
DECLARE #F3 int
DECLARE #f4 char(10)
SELECT #f1 = FIELD1 from MYTABLE1
SELECT #F2 = FIELD2 FROM MYTABLE2
SELECT #F3 = FIELD3, #F4=FIELD4 FROM MYTABLE3
/* NOW return the result set to the user, it'll come back just like a regular select */
SELECT #F1 AS F1, #F2 AS F2, #F3 AS F3, #F4=F4
The presence or absence of primary or foreign keys doesn't prevent you from joining the tables. (It won't be particularly fast, but you can do it.) Neither does their existing in separate database instances.
You say that your databases aren't linked. From this, I have to infer that the database you're writing the stored procedure in likely has no access to the 2nd database; if that's the case, you won't be able to access it anyway. You need to add a link to the 2nd database using Enterprise Manager.
Once you've done that, you can reference the tables in the 2nd database using its schema name as below:
SELECT *
FROM foo.employees
where foo is the schema name.
Good luck.
SELECT Field1, Field2, Field3 FROM Table1
UNION ALL
SELECT F1, F2, F3 FROM Table2
UNION ALL
SELECT Fld1, Fld2, Fld3 FROM Table3;
This will pull all data from all three tables into single output.
Check that other table fields match type of the first table and you are good to go.