Migrate data from non Normalized database to a well Design database - sql-server

I am migrating reads from a poorly design table to the newly Normalize one in sqlserver 2008.
My goal here is to get a count of total record in the Source table store in in a variable. The loop through each row and insert to the destination table. I have made numerous search on similar posts:
1: How do I insert a record from one table into another table? and Inserting into database by reading another
But was able to modify a code from SQL Examples
Now am get this error:
Msg 207, Level 16, State 1, Line 5
Invalid column name 'Num_Row_in_table
Code:
DECLARE #i INT
DECLARE #Num_Row_in_table int
SET #i=1
WHILE(#i <= Num_Row_in_table)
BEGIN
Insert into Destinationtable (FirstName,LastName,Photo,SN)
(
Select FirstName,LASTNAME,Photo,SN From MyDB.dbo.sourcetable
)
SET #i=#i+1
END

Forget the cursor; just do this:
Insert into Destinationtable (FirstName,LastName,Photo,SN)
Select FirstName,LASTNAME,Photo,SN From MyDB.dbo.sourcetable

Related

Is it possible to write to the same temp table using SELECT INTO?

I am trying to write to a temp table , the source data can come from two different sources but they do have the same schema. the source of data is selected by a conditional statement IF ELSE only one can execute, but sql doesn't seem to like that . it complains the table already exists. here is the piece of code. "Msg 2714, Level 16, State 1, Procedure sp_xxx, Line 37 [Batch Start Line 0]
There is already an object named '#my_temp_table' in the database. "
IF #flag = 0
SELECT * INTO #my_temp_table
FROM source_A
ELSE
BEGIN
--even tho the temp table will not exist i am trying to by pass the error
IF OBJECT_ID('tempdb..#my_temp_table ') IS NOT NULL
DROP TABLE #my_temp_table
SELECT * INTO #my_temp_table
FROM source_B
END
There are a couple of things going on here that are or will be issues for you.
SQL Server's SELECT...INTO logic is how Microsoft chose to implement the more standard CREATE TABLE AS... syntax (which is then followed by a SELECT statement in most dialects). You can only create that table once, and then it's there.
Local temp tables (with a single #) continue to exist until your session disconnects from the instance. So if you try to run the above code twice without disconnecting, it'll fail.
You're using SELECT *, which is going to bite you when somebody changes the schema of one source table.
All that said, you don't need all that logic. You can do what you want with one query.
SELECT
<Column List>
INTO #my_temp_table
FROM
source_A
WHERE #flag = 0
UNION
SELECT
<Column List>
FROM
source_B
WHERE #flag <> 0;

Issue truncating a table over linked server

I'm trying to write a stored procedure that truncates the first table on our data warehouse, then copies data from our local database to the DWH server.
Here's the code:
USE [ARGTPAWN-DB-DWH].[DWH].[dbo].[PML];
GO
TRUNCATE TABLE [ARGTPAWN-DB-DWH].[DWH].[dbo].[PML];
GO
SELECT *
INTO [ARGTPAWN-DB-DWH].[DWH].[dbo].[PML]
FROM [14TPAWNDB001].[FLMedicaid].[dbo].[PML]
GO
And the response I am getting is:
Msg 911, Level 16, State 1, Line 1
Database 'ARGTPAWN-DB-DWH' does not exist. Make sure that the name is entered correctly.
Msg 4701, Level 16, State 1, Line 3
Cannot find the object "PML" because it does not exist or you do not have permissions.
Msg 117, Level 15, State 1, Line 7
The object name 'ARGTPAWN-DB-DWH.DWH.dbo.PML' contains more than the maximum number of prefixes. The maximum is 2.
The servers are already linked, so that is not an issue, but I'm very curious as to why this is not working.
Linked Server and distributed query can be tricky in term of performance...
You should consider to write the Stored Procedure on the database that hosts the target tables even if you call it from the database that hosts the source tables.
On target database :
CREATE PROCEDURE [DBO].[TARGET_SIDE_PS]
AS
-- For error handling.
DECLARE #aERROR int
DECLARE #aCOUNT int
-- Start transaction.
BEGIN TRANSACTION
-- Drop target table.
IF OBJECT_ID('dbo.PML', 'U') IS NOT NULL
DROP TABLE dbo.PML;
-- Error catching
SELECT #aERROR = ##ERROR, #aCOUNT = ##ROWCOUNT
IF #aERROR<>0
BEGIN
-- Error : do what is needed.
--
ROLLBACK TRANSACTION
RETURN 1
END
SELECT *
INTO dbo.PML
FROM [SOURCELINKEDSERVER].[SOURCEDATABASE].[dbo].[PML]
-- Error catching
SELECT #aERROR = ##ERROR, #aCOUNT = ##ROWCOUNT
IF #aERROR<>0
BEGIN
-- Error : do what is needed.
--
ROLLBACK TRANSACTION
RETURN 2
END
IF #aCOUNT <= 0
BEGIN
-- No data: do what is needed.
--
PRINT 'NO DATA !!'
END
COMMIT TRANSACTION
RETURN 0
Call the target side PS from the source side (or from the target side) and it's done but source side database have to be linked to target side database.
Transaction can be remove due to DROP/CREATE/INSERT sequence.
You can do the oposite : PS on the source side, with drop and insert on the linked target side server database, but you must know :
- transaction will take a while.
- all the source data will be locked during the whole process.
- INSERT will take a while.
You don't need to execute:
USE [ARGTPAWN-DB-DWH].[DWH].[dbo].[PML];
Simply execute the lines below.
What is ARGTPAWN-DB-DWH? If this is the server name it is not needed.
Your USE statement should refer to the database only.
Your SELECT * INTO... will attempt to create the table PML, if this already exists (which it will if you are performing a truncate) it will fail - Use INSERT INTO... or DROP TABLE... instead of truncate.
Don't use SELECT *.

There already exists an object in the database SQL Server

I have created a stored procedure that returns the id of last inserted row of a table based on one condition.
Condition is such that if the row being inserted already exists then it takes identity column of the row otherwise it inserts a new row into the table.
To do this, I have written the following code in a stored procedure
ALTER PROCEDURE [dbo].[Test_Procedure]
#description nvarchar(max)
AS
BEGIN
DECLARE #tempId int;
SELECT CommentId
INTO tempId
FROM TestTable
WHERE description = #description;
IF #tempId IS NULL
BEGIN
INSERT INTO TestTable
VALUES (#description);
SELECT scope_identity();
END
ELSE
BEGIN
SELECT #tempId FROM dual;
END
DROP TABLE tempId;
END
When I run the above stored procedure, first time it ran successfully and then on wards it started throwing the following error message
Msg 2714, Level 16, State 6, Procedure Test_Procedure, Line 15
There is already an object named 'tempId' in the database.
The bit I'm not understanding is tempId is used as a variable not as a table. I have seen people with the similar problem but in their case they used temporary tables
I really appreciate your help in resolving the above issue.
Try this syntax for setting your variable.
SELECT #tempId = CommentId from TestTable where description = #description;
Currently your 'select into' is creating a table 'tempId' on the database.

insert then and update then in sybase

I did a search over the net but I couldnt find my answer
in oracle , if we to specify for the trigere if its insert or update , we write like this :
create or replace trigger TRG_LOGS
after INSERT or update or delete
ON TABOE_LOGS
FOR EACH ROW
DECLARE
V_USERNAME VARCHAR2(100);
BEGIN
if inserting then
insert into long_log(NAME) VALUE (:new.NAME)
ELSE if UPDATING THEN
insert into long_log(NAME) VALUE (:OLD.NAME)
END;
END;
Is throwing an error on Incorrect syntax near the keyword 'insert'.
For Sybase, each action is a seperate trigger:
create trigger TRG_LOGS_INS on TABOE_LOGS
for INSERT
as
DECLARE #V_USERNAME varchar(100)
BEGIN
insert into long_log
select NAME from INSERTED
END
....
create trigger TRG_LOGS_UPD on TABOE_LOGS
for UPDATE
as
DECLARE #V_USERNAME varchar(100)
BEGIN
insert into long_log
select NAME from DELETED
END
Not sure if my syntax is exactly right, but should get you pointed in the right direction. The INSERTED table (similar to Oracles new) stores the new records on either an insert or update action. The DELETED table (similar to Oracles old) stores the old records on either an update or delete action.
More information and examples can be found in the Sybase T-SQL Users Guide: Triggers

Cross-database trigger in SQL Server

I have two tables CrossDBTrigTest_1 and CrossDBTrigTest_2 on same SQL Server instance.
The databases both have a table called Employee.
I wrote the following trigger on the Employee table CrossDBTrigTest_1 db:
Create Trigger [dbo].[CrossDBInsert] on [dbo].[employee] after insert
AS
Begin
Set nocount on
Insert into CrossDBTrigTest_2.employee(FirstName, LastName, Date)
SELECT inserted.FirstName, inserted.LastName, getdate()
FROM inserted
End
but the Insert statement fails with message:
Msg 208, Level 16, State 1, Procedure CrossDBInsert, Line 5
Invalid object name 'CrossDBTrigTest_2.employee'.
How do I enable cross database triggers in situations like this??
Shouldn't
CrossDBTrigTest_2.employee(FirstName,LastName,Date)
be
CrossDBTrigTest_2.dbo.employee(FirstName,LastName,Date)
???
Use
CrossDBTrigTest_2..employee
as table name. Note two dots instead of one.

Resources