Trigger two tables from two different databases to insert data (SQL Server) - sql-server

What the title says, I want to insert data from a database to another database. The first database "DB1" is the source and the second database "DB2" is the target.
The relevant tables are defined as follows:
DB1 => tbl_Target
==================================
Id | Date | Name | Age | Num_Aucts
==================================
DB2 => tbl_Source
======================
Name | Age | Num_Aucts
======================
Well, tbl_Source contains 40 rows of data. I need to transfer these rows into tbl_Target. But how you can see tbl_Target has two additional columns Idand Date. Id will set automatically. The important column is Date. In this column I want to set the currently date. In this case from today. How can I define this in a trigger frunction in SQL Server with T-SQL?
I have begun in this direction:
USE DB1
GO
CREATE TRIGGER trg_Insert_tblSource ON tbl_Source
FOR INSERT AS
BEGIN
INSERT INTO DB2.dbo.tbl_Target ([Date], [Name], [Age], [Num_Aucts])
SELECT ??? // How to get the current date?
Can anyone help me? Do I need a stored procedure?

I don't know if I fully understood your question. But if you just want to transfer the data from one table to another, you don't need a trigger. You could achieve this with a simple INSERT...SELECT:
INSERT INTO DB2.dbo.tbl_Target (
[Date],
[Name],
[Age],
[Num_Aucts]
)
SELECT GETDATE(), [Name], [Age], [Num_Aucts]
FROM yourDB.dbo.tbl_Source
If you want to use a trigger, write the following in the BEGIN block:
INSERT INTO DB2.dbo.tbl_Target (
[Date],
[Name],
[Age],
[Num_Aucts]
)
SELECT GETDATE(), [Name], [Age], [Num_Aucts]
FROM inserted
The trigger gets fired each time you insert data into tbl_Source. But the existing data doesn't get inserted into tbl_Target with your trigger.

you can use GetDate() to get current date of server
USE DB1
GO
CREATE TRIGGER trg_Insert_tblSource ON tbl_Source
FOR INSERT AS
BEGIN
INSERT INTO DB2.dbo.tbl_Target (
[Date],
[Name],
[Age],
[Num_Aucts]
)
SELECT GETDATE(), [Name], [Age], [Num_Aucts]
FROM inserted;
END
GO

Related

SQL inserting data based on nested xpath

I have a simple insert statement that I am working on. This query inserts a core record, returns an ID, and then inserts a one or more tasks into another table. For each of those tasks, I need to do an additional insert into a 3rd table.
I am having a little trouble trying to figure out how to set this up due to the second insert statement happening before the 3rd, so I am not sure about how to get the identity from each insert to pass to query 3.
DECLARE #requestID INT;
-- Insert the core request details
INSERT INTO esas.Request (Requestor, Justification, CreatedBy, DateCreated)
SELECT #requestor,
#justification,
#creator,
GETUTCDATE()
-- Define the core request ID
SET #requestID = SCOPE_IDENTITY();
-- Add tasks
INSERT INTO esas.Task
( RequestID ,
ToolID ,
QID ,
Action
)
SELECT #requestID,
ParamValues.x1.value('tool[1]', 'INT'),
ParamValues.x1.value('user[1]', 'VARCHAR(10)'),
ParamValues.x1.value('action[1]', 'INT)')
FROM #tasks.nodes('/request/task') AS ParamValues(x1);
-- For each task, add any associated roles (stuck here)
INSERT INTO esas.TaskRoles
( TaskID,
RoleID,
ActionID )
VALUES ( 0, -- TaskID - int
0, -- RoleID - int
0 -- ActionID - int
)
In the last insert, I need to pass the PK/AI the TaskID created from "Add Tasks" to another table, along with the roleID and action from the XML string.
Here is my XML structure:
<request>
<task>
<tool>123</tool>
<user>4567</user>
<roles>
<role>
<roleID>12</roleID>
<action>1</action>
</role>
<role>
<roleID>1245</roleID>
<action>0</action>
</role>
<role>
<roleID>678</roleID>
<action>1</action>
</role>
</roles>
</task>
</request>
My confusion is due to knowing that INSERT INTO esas.Task is going to all happen at once before moving on so I am not sure how to pass each identity to the next insert along with its corresponding details in the XML structure.
I figured this out using xpath and joining the tasks table after the data had been inserted.
-- For each task, add any associated roles
INSERT INTO esas.TaskRoles
( TaskID,
RoleID,
ActionID )
SELECT t.TaskID,
ParamValues.x1.value('roleID[1]', 'INT'),
ParamValues.x1.value('action[1]', 'INT')
FROM esas.Task AS t
JOIN #tasks.nodes('/request/task/roles/role') AS ParamValues(x1)
ON t.RequestID = #requestID
AND t.ToolID = ParamValues.x1.value('../../tool[1]', 'INT')
AND t.QID = ParamValues.x1.value('../../user[1]', 'VARCHAR(10)')

Updating and Inserting to 2 different tables from the Same package

I have 2 tables called Customer and ChangeLog. having the following structure
Customer table
ChangeLog Table
My Requirement is that
I need an SSIS Package that will read the record from another table with the same structure as CustomerTable and then compare the rows on both tables. If a change in any record is found it updates the records in the customer table as well as put an entry in the ChangeLog saying which column was updated.
So when a change is found in any of the columns I need to do the following
Update the Coresposing record in the Customer Table
Insert a new row into the ChangeLog
There won't be an Insert to the Customer Table. There will be only updates
Is there any single Task in SSIS that I can use to do both the update as well as an insert to these different tables ? or else what is the quickest and efficient way to achieve this in SSIS?
Any help is much appreciated
No there is no single SSIS task made to do this. I wouldn't use SSIS for this at all. Put the logic in either a stored procedure or trigger. If you have to use SSIS for some reason, then have SSIS call the stored procedure, or UPDATE the table and let the trigger fire.
This here is better than a SSIS packages since you can use a trigger to detect your row changes, and even the values.
Try my example you can just C/P into management studio. When you update on Sample_Table you will have changes rows and which column in your table.
So what you can do is. Keep your lookup logic in SSIS (if you want something in SSIS) - Updated the Table based on matches in lookup
When these updates happend your trigger will be fired and update the rows that have changed.
Alternative you can create your lookup in a t-sql script and do an ordinary update when custid=custid instead its just as easy. But thats up to you.
EDITED
-- -------------------- Setup tables and some initial data --------------------
CREATE TABLE dbo.Sample_Table (ContactID int, Forename varchar(100), Surname varchar(100), Extn varchar(16), Email varchar(100), Age int );
INSERT INTO Sample_Table VALUES (1,'Bob','Smith','2295','bs#example.com',24);
INSERT INTO Sample_Table VALUES (2,'Alice','Brown','2255','ab#example.com',32);
INSERT INTO Sample_Table VALUES (3,'Reg','Jones','2280','rj#example.com',19);
INSERT INTO Sample_Table VALUES (4,'Mary','Doe','2216','md#example.com',28);
INSERT INTO Sample_Table VALUES (5,'Peter','Nash','2214','pn#example.com',25);
CREATE TABLE dbo.Sample_Table_Changes (ContactID int, FieldName sysname, FieldValueWas sql_variant, FieldValueIs sql_variant, modified datetime default (GETDATE()));
GO
-- -------------------- Create trigger --------------------
CREATE TRIGGER TriggerName ON dbo.Sample_Table FOR DELETE, INSERT, UPDATE AS
BEGIN
SET NOCOUNT ON;
--Unpivot deleted
WITH deleted_unpvt AS (
SELECT ContactID, FieldName, FieldValue
FROM
(SELECT ContactID
, cast(Forename as sql_variant) Forename
, cast(Surname as sql_variant) Surname
, cast(Extn as sql_variant) Extn
, cast(Email as sql_variant) Email
, cast(Age as sql_variant) Age
FROM deleted) p
UNPIVOT
(FieldValue FOR FieldName IN
(Forename, Surname, Extn, Email, Age)
) AS deleted_unpvt
),
--Unpivot inserted
inserted_unpvt AS (
SELECT ContactID, FieldName, FieldValue
FROM
(SELECT ContactID
, cast(Forename as sql_variant) Forename
, cast(Surname as sql_variant) Surname
, cast(Extn as sql_variant) Extn
, cast(Email as sql_variant) Email
, cast(Age as sql_variant) Age
FROM inserted) p
UNPIVOT
(FieldValue FOR FieldName IN
(Forename, Surname, Extn, Email, Age)
) AS inserted_unpvt
)
--Join them together and show what's changed
INSERT INTO Sample_Table_Changes (ContactID, FieldName, FieldValueWas, FieldValueIs)
SELECT Coalesce (D.ContactID, I.ContactID) ContactID
, Coalesce (D.FieldName, I.FieldName) FieldName
, D.FieldValue as FieldValueWas
, I.FieldValue AS FieldValueIs
FROM
deleted_unpvt d
FULL OUTER JOIN
inserted_unpvt i
on D.ContactID = I.ContactID
AND D.FieldName = I.FieldName
WHERE
D.FieldValue <> I.FieldValue --Changes
OR (D.FieldValue IS NOT NULL AND I.FieldValue IS NULL) -- Deletions
OR (D.FieldValue IS NULL AND I.FieldValue IS NOT NULL) -- Insertions
END
GO
-- -------------------- Try some changes --------------------
UPDATE Sample_Table SET age = age+1;
/*UPDATE Sample_Table SET Extn = '5'+Extn where Extn Like '221_';
DELETE FROM Sample_Table WHERE ContactID = 3;
INSERT INTO Sample_Table VALUES (6,'Stephen','Turner','2299','st#example.com',25);
UPDATE Sample_Table SET ContactID = 7 where ContactID = 4; --this will be shown as a delete and an insert
-- -------------------- See the results --------------------
SELECT *, SQL_VARIANT_PROPERTY(FieldValueWas, 'BaseType') FieldBaseType, SQL_VARIANT_PROPERTY(FieldValueWas, 'MaxLength') FieldMaxLength from Sample_Table_Changes;
-- -------------------- Cleanup --------------------
DROP TABLE dbo.Sample_Table; DROP TABLE dbo.Sample_Table_Changes;*/
select * from dbo.sample_table_changes

Stored Procedure not executing in SQL SERVER?

I'm trying to write a somewhat simple stored procedure. I first want to verify if there is anything in the table; if there is to TRUNCATE it, if there isn't to populate it with some data. What happens is, it gets execute without any error, but nothing happens to the table. It is as it was before executing it.........empty.
ALTER PROCEDURE [dbo].[LoadReportDataCI]
AS
If (Select Count(*) from tbl_TempTableReport)>0
BEGIN
Truncate table tbl_TempTableReport
END
Begin
INSERT INTO tbl_TempTableReport (userID, VendorID, VendorName, UnitCost, UnitCount, CostValue)
SELECT
'1234',
VendorID,
VendorName,
InvValue,
BegInvOnHand,
BegCurrentValue
From vVendorsAndInvONHand
END
If I highlight starting at INSERT until the END, the data gets populated in the table, but otherwise it doesn't work. Shed some light anyone?
There is no point to checking if there are rows before truncating. It is far faster to just truncate than checking for the existence of rows. If there are no rows it will still run just fine.
ALTER PROCEDURE [dbo].[LoadReportDataCI]
AS
Truncate table tbl_TempTableReport;
INSERT INTO tbl_TempTableReport
(
userID
, VendorID
, VendorName
, UnitCost
, UnitCount
, CostValue
)
SELECT
'1234'
, VendorID
, VendorName
, InvValue
, BegInvOnHand
, BegCurrentValue
From vVendorsAndInvONHand;
Use below code to execute your stored procedure, I have moved your second begin after AS
ALTER PROCEDURE [dbo].[sp_LoadReportDataCI]
AS
Begin
If (Select Count(*) from tbl_TempTableReport)>0
BEGIN
Truncate table tbl_TempTableReport
END
INSERT INTO tbl_TempTableReport (userID, VendorID, VendorName, UnitCost, UnitCount, CostValue)
SELECT
'1234',
VendorID,
VendorName,
InvValue,
BegInvOnHand,
BegCurrentValue
From vVendorsAndInvONHand
END
I guess, you didn't execute the Stored Procedure. Did you EXEC the LoadReportDataCI after running the ALTER script?

Create trigger to only allow updates for certain employees

We have a database with one table for all of our Employee information, (name, pay, etc). One of the columns in the table is "commission." I am trying to write a trigger that will only allow the "commission" column be updated or inserted into if it is for a Sales Representative. If an update is tried on any other employee then it should print out an error. I would like this trigger to also print all of the information from each update, failed or not, to a separate table. What is the best way for me to go about doing this?
I am relatively new to SQL Server so any help here would be greatly appreciated!
Thanks,
EDIT:
Here is what i have so far:
CREATE TRIGGER CommissionUpdate ON Employees
FOR UPDATE
AS IF UPDATE(Commission)
Declare
#Old_Comm money
, #New_Comm money
, #EmpID int
Select #EmpID = (Select EmployeeID From Deleted)
Select #Old_Comm = (Select Commission From Deleted)
Select #New_Comm = (Select Commission From Inserted)
BEGIN
INSERT INTO ChangeLog (EmpID, [User], [Date], OldComm, NewComm)
VALUES (#EmpID, User_Name(), GetDate(), #Old_Comm, #New_Comm)
END
Basically all this does is add entries to the ChangeLog table when the commission table is updated. Im still having trouble adding the constraints to only allow "commission" to be updated for Sales Reps.

Insert records into table in SQL server

Is there a way in SQL SERVER(05 & 08) that I can insert records from an external file into a temp table? I do not have privilege to the database at all. Here is what i tried to do:
CREATE table #temp
(KEY_ID INT)
INSERT INTO #temp
SELECT 90883000
Ran #temp table with result:
KEY_ID
---------
90883000
It kind of works with just one record. How do I do if I have hundred records? Thanks a lot!!!
This just to show how to add multiple rows in a table.
CREATE table #temp(
KEY_ID integer
)
Declare #i as int
set #i = 1
WHILE (#i <= 10000)
BEGIN
insert into #temp values(#i)
set #i += 1
End
How about a table variable. I believe that the #temp need rights to the tempdb database. I believe that a table variable is used just like any other variable which is session based.
To declare a table variable:
DECLARE #ProductTotals TABLE
(
ProductID int,
Revenue money
)
Insert into a table variable:
INSERT INTO #ProductTotals (ProductID, Revenue)
SELECT ProductID, SUM(UnitPrice * Quantity)
FROM [Order Details]
GROUP BY ProductID
For importing files, you can use BULK IMPORT. Use this to get the data into your temp table, then you can run set based operations against it.
A more effective way of inserting a lot of rows.
INSERT INTO #temp
(KeyID)
SELECT TOP 1000 -- PUT YOUR QUANTITY HERE
IDENTITY(INT,1,1) AS N
FROM Master.dbo.SysColumns sc1,
Master.dbo.SysColumns sc2
If you're going to be using this a lot, just ask them to create you a TALLY TABLE.
This is how I usually do it if I have the values in a file somewhere. Inserting hundreds of records from flat text file into temp table. My example only has one column, but as long as the flat file is delimited somehow, you can do as many columns as needed. Need to make sure you put the text file in a directory you have access to.
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL DROP TABLE #TempTable
CREATE TABLE #TempTable(Col1 varchar(10)) --Specify temp-table name & columns
BULK INSERT #TempTable
FROM 'C:\FileName.txt' --Specify file path/name
WITH (
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\n'
);
GO

Resources