I have Employees tables in the database with a column EmpID which was changed to ID. I want to use the same query in both the old and new table and get the same result depending on the condition.
I have tried the following:
IF (COL_LENGTH('Employees', 'EmpID') IS NOT NULL)
SELECT EmpID, NAME, SEX, SALARY
FROM Employees
WHERE EmpID IS NOT NULL
ELSE
SELECT ID, NAME, SEX, SALARY
FROM Employees
WHERE ID IS NOT NULL
But when I run the query in the new table, I get column name EmpID doesn't exist error. Any help is appreciated!
You can do this without dynamic SQL using this approach.
SELECT ISNULL(CA.ID, CA.EmpID) AS ID,
CA.NAME,
CA.SEX,
CA.SALARY
FROM (VALUES(NULL, NULL)) V(ID, EmpID)
CROSS APPLY (SELECT ID, /*Resolved from Employees if present or "V" otherwise */
EmpID, /*Resolved from Employees if present or "V" otherwise */
NAME,
SEX,
SALARY
FROM Employees) CA
WHERE ISNULL(CA.ID, CA.EmpID) IS NOT NULL;
Demo
The issue is the compile stage versus the execution stage. The code is initially compiled, where the tables and columns are validated.
Your problem is that the column doesn't exist, so you are getting a compile failure.
You can fix this using dynamic SQL:
DECLARE #sql NVARCHAR(max);
IF (COL_LENGTH('Employees', 'EmpID') IS NOT NULL)
SET #sql = N'
Select EmpID, NAME, SEX, SALARY
From Employees
Where EmpID IS NOT NULL'
ELSE
SET #sql = N'
Select ID, NAME, SEX, SALARY
From Employees
Where ID IS NOT NULL'
EXEC sp_executesql #sql;
I have select like this:
SELECT UserName FROM Users WHERE userId= #UserId;
I want to get this value and use as register into insert
I try:
INSERT INTO Product.ProductDetail VALUES (
SELECT UserName FROM Users WHERE userId= #UserId;
);
but I get invalid column, how is the correct way to do this?
Your syntax is incorrect. The proper way does not have VALUES keyword in INSERT INTO...SELECT
INSERT INTO Product.ProductDetail (ColumnName) -- Must specify target column if you have multiple columns in the table
SELECT UserName
FROM Users
WHERE userId= #UserId
INSERT INTO Product.ProductDetail (UserName)
SELECT UserName FROM Users WHERE userId= #UserId
You'll need to specific insert column names if you have auto increment key in your table to be inserted.
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
I have this Select statement
select Id, UserName, from UserTable where Department= #DepartmentInput
and a variable to calculate how many users from the department
#UserCounter
Is there a way to add count(the number of users from the department) into #UserCounter from the select statement should the statement runs in a while loop?
Presuming sql-server:
select Id, UserName, #UserCounter = Count(*) OVER (Partition By Department)
from UserTable
where Department= #DepartmentInput
Otherwise a simple sub-query should work too:
select Id, UserName, #UserCounter = (select count(*) from UserTable
where Department= #DepartmentInput)
from UserTable
where Department= #DepartmentInput
The database should be clever enough to optimize that query so that the subquery doesn't need to be avaulated for every (matching) row.
I have a series of queries being UNION'd together. Each query has a WHERE... IN clause that compares against the same list of IDs.
In a simplified form for example purposes it looks like this:
SELECT * FROM MyTable
WHERE AuthorUserId IN (SELECT UserId FROM Users WHERE TeamId = #teamId)
UNION
SELECT * FROM MyTable
WHERE PublisherUserId IN (SELECT UserId FROM USERS WHERE TeamId = #teamId)
UNION...
and so on. #teamId is an int stored procedure parameter.
Is there a way to tell SQL Server to hold on to the result set of
SELECT UserId FROM USERS WHERE TeamId = #teamId
so it doesn't fetch it for each SELECT?
One way you could do this is by capturing the results of that query and storing it in a temp table, and JOINing to those results in your query:
Declare #UserIds Table (UserId Int)
Insert #UserIds (UserId)
SELECT UserId
FROM Users
WHERE TeamId = #teamId
SELECT M.*
FROM MyTable M
JOIN #UserIds U ON M.AuthorUserId = U.UserId
UNION
SELECT M.*
FROM MyTable M
JOIN #UserIds U ON M.PublisherUserId = U.UserId
UNION...
SQL server is smart enough to store results of same query if the parameters are same. If your subquery is not using session variables, you will be fine. You can also put index on TeamId which will make this query faster.
If you are still worried about it and using any programming language to get data from SP, then you should store it in a variable in code and then pass that result set into SP.
Second option would be to store it in temp table and then query it from temp table