MS SQL: alter indexed view by including additional columns from new table - sql

I need to update existing MS SQL indexed view by including additional columns values from newly created table.
Indexed view:
CREATE OR ALTER VIEW [dbo].[MySelectionInfo]
WITH schemabinding
AS
SELECT C.Id id0,
C.Code Code1,
C.Name Name2,
C.ProgramLevel Level3,
C.Department Department4,
C.City City10,
C.STATE State11,
C.StartDate StartDate12,
C.Deadline Deadline13,
B.ID Table_B_ID,
A.Id Table_A_ID
FROM dbo.Table_A A
INNER JOIN dbo.Table_B B ON A.id = B.Table_A_Id
INNER JOIN dbo.Table_C C ON C.Table_B_Id = B.Id
New table:
CREATE TABLE [dbo].[Table_D] (
[Id] [int] IDENTITY (1, 1) PRIMARY KEY NOT NULL,
[ModelName] [varchar](max) NOT NULL,
[Table_C_Id] [int] NOT NULL,
[AttributeValue] [varchar](max) NOT NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
CONSTRAINT FK_Table_C_Id FOREIGN KEY (Table_C_Id) REFERENCES some_schema.dbo.[Table_C] (Id)
ON DELETE CASCADE
ON UPDATE CASCADE
)
Data in the new table:
I want to include only some of the ModelName column values as a column names and AttributeValue as values in the select * from [dbo].[MySelectionInfo] result set:
I can achieve the desired result using the PIVOT function:
CREATE OR ALTER VIEW [dbo].[MySelectionInfo]
WITH schemabinding
AS
SELECT C.Id id0,
C.Code Code1,
C.Name Name2,
C.StartDate StartDate12,
C.Deadline Deadline13,
B.ID Table_B_ID,
A.Id Table_A_ID
FROM dbo.Table_A A
INNER JOIN dbo.Table_B B ON A.id = B.Table_A_Id
INNER JOIN dbo.Table_C C ON C.Table_B_Id = B.Id
LEFT JOIN (SELECT PivotTable.Table_C_Id,
PivotTable.attribute1,
PivotTable.attribute2,
PivotTable.attribute3
FROM (SELECT Table_D.Table_C_Id,
Table_D.ModelName,
Table_D.AttributeValue
FROM dbo.Table_C
INNER JOIN dbo.Table_D
ON Table_C.Id = Table_D.Table_C_Id) AS sourceTable
PIVOT (
Max(AttributeValue) FOR ModelName IN (attribute1, attribute2, attribute3)
) AS PivotTable) dbo.Table_D D ON D.Table_C_Id = C.Id
But, after running the SQL statement above, I am not be able to create the clustered index for the view, because LEFT JOIN, PIVOT, MAX are prohibited to be used in the indexed views.
Question: Is there any other solutions to achieve the desired result and still have an existing view as an Indexed view?

if your data allow it, you could cross tab with case statements instead of PIVOTing:
/*
drop view dbo.mytestinfoview;
go
drop table dbo.Table1;
go
--*/
create table dbo.Table1
(
id int,
ModelName varchar(20),
AttributeValue int
);
insert into dbo.Table1(id, ModelName, AttributeValue)
select distinct o.object_id, concat('attribute', v.id), o.attributevalue
from
(
select
object_id ,
abs(checksum(newid())) % 2 as attributevalue
from sys.objects
) as o
cross apply (values(1), (2), (3), (4)) as v(id)
go
create or alter view dbo.mytestinfoview
with schemabinding
as
select id, count_big(*) as thecounter,
sum(isnull(case ModelName when 'attribute1' then AttributeValue end, 0)) as attribute1,
sum(isnull(case ModelName when 'attribute2' then AttributeValue else 0 end, 0)) as attribute2,
sum(isnull(case ModelName when 'attribute3' then AttributeValue else 0 end, 0)) as attribute3
from dbo.Table1
group by id
go
create unique clustered index idx_v1 on dbo.mytestinfoview(id);
go
select * from dbo.mytestinfoview;
go

Related

How to capture columns from joined tables using output clause?

I am updating a table called tableA by joining tableB and tableC at the same time I am capturing updated records into temp table using output clause from tableA . Now I want capture columns from table B for the updated data but output clause isn't allowing the same.
Eg:
Update SLC Set SLC.Datascrublevel = C.Datascrublevel
OUTPUT [Deleted].Systemcode,
[Deleted].Systemkey,
[Deleted].datascrublevel,
[Inserted].datascrublevel
INTO #TEMP1
FROM TABLEA SLC with(nolock)
INNER JOIN TABLEB SC ON SC.SystemCode = SLC.SystemCode
INNER JOIN TABLEC SL ON SL.SystemCode = SLC.SystemCode and SLC.SystemKey = SL.Systemkey
INNER JOIN #TEMP C ON SLC.Datascrublevel <> C.DataScrubLevel AND C.Systemcode = SLC.SystemCode and C.Systemkey = SLC.SystemKey
Now I want columns from tableB to capture into temp table using output clause. Please provide your advise if there are any alternative ways.
Just Like you have given it as [deleted].[Column Name] and [Inserted].[Column Name] add one more column as [SC].[Column Name]
Example :
IF OBJECT_ID('TempDb..#TABLEA') IS NOT NULL
DROP TABLE #TABLEA
IF OBJECT_ID('TempDb..#TABLEB') IS NOT NULL
DROP TABLE #TABLEB
IF OBJECT_ID('TempDb..#TABLEC') IS NOT NULL
DROP TABLE #TABLEC
IF OBJECT_ID('TempDb..#TABLED') IS NOT NULL
DROP TABLE #TABLED
CREATE TABLE #TABLEA
(
SeqNo INT IDENTITY(1,1),
MyDate DATE
)
CREATE TABLE #TABLEB
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20)
)
CREATE TABLE #TABLEC
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20),
MyDate DATE
)
CREATE TABLE #TABLED
(
SeqNo INT,
MyDate DATE,
FullName VARCHAR(20)
)
INSERT INTO #TABLEA
(
MyDate
)
SELECT GETDATE()
UNION
SELECT GETDATE()+1
UNION
SELECT GETDATE()-1
INSERT INTO #TABLEB
(
FullName
)
VALUES('A'),('B'),('C')
INSERT INTO #TABLEC
(
FullName
)
VALUES('A'),('B'),('C')
UPDATE C
SET MyDate = A.MyDate
OUTPUT
deleted.SeqNo,
deleted.MyDate,
B.FullName
INTO #TABLED
FROM #TABLEC C
INNER JOIN #TABLEB B
ON C.FullName = B.FullName
INNER JOIN #TABLEA A
ON A.SeqNo = B.SeqNo
SELECT * FROM #TABLED

Merging two parent > child table sets

I need to get the data in two parent > child table sets merged/combined into a third parent > child table.
The tables look like this:
The only difference in the three sets of tables is that TableC has a TableType column to help discern the difference between a TableA record and a TableB record.
My first thought was to use a cursor.. Here's code to create the table structure, insert some records, and then merge the data together. It works very well, sooooo....
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
-- Needed throughout..
DECLARE #ID INT
-- Merge TableA and TableAChild into TableC and TableCChild
DECLARE TableACursor CURSOR
-- Get the primary key from TableA
FOR SELECT ID FROM TableA
OPEN TableACursor
FETCH NEXT FROM TableACursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
-- INSERT INTO SELECT the parent record into TableC, being sure to specify a TableType
INSERT INTO TableC (Name, TableType) SELECT Name, 'A' FROM TableA WHERE ID = #ID
-- INSERT INTO SELECT the child record into TableCChild using the parent ID of the last row inserted (SCOPE_IDENTITY())
-- and the current record from the cursor (#ID).
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableAChild WHERE Parent = #ID
FETCH NEXT FROM TableACursor INTO #ID
END;
CLOSE TableACursor
DEALLOCATE TableACursor
-- Repeat for TableB
DECLARE TableBCursor CURSOR
FOR SELECT ID FROM TableB
OPEN TableBCursor
FETCH NEXT FROM TableBCursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO TableC (Name, TableType) SELECT Name, 'B' FROM TableB WHERE ID = #ID
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableBChild WHERE Parent = #ID
FETCH NEXT FROM TableBCursor INTO #ID
END;
CLOSE TableBCursor
DEALLOCATE TableBCursor
Now, my question(s):
I've always been told that cursors are bad. But I couldn't find another way of doing it. I'm wondering if there's some way to do that with a CTE?
If the cursor is appropriate in this situation, how did I do? Is there a better way of doing what I did? It doesn't look very DRY to me, but I'm no SQL expert.
Lastly, if you want to re-run the query above, here's a small script to delete the tables that were created.
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
The correct result should look like:
You can use merge as described by Adam Machanic in Dr. OUTPUT or: How I Learned to Stop Worrying and Love the MERGE and in this question to get a mapping between the new identity value and the old primary key value in a table variable and the use that when you insert to your child tables.
declare #T table(ID int, IDC int);
merge dbo.TableC as C
using dbo.TableA as A
on 0 = 1
when not matched by target then
insert (TableType, Name) values('A', A.Name)
output A.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, AC.Name
from dbo.TableAChild as AC
inner join #T as T
on AC.Parent = T.ID;
delete from #T;
merge dbo.TableC as C
using dbo.TableB as B
on 0 = 1
when not matched by target then
insert (TableType, Name) values('B', B.Name)
output B.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, BC.Name
from dbo.TableBChild as BC
inner join #T as T
on BC.Parent = T.ID;
SQL Fiddle
Here is one way to do this without a cursor or other RBAR type stuff.
ALTER TABLE TableC ADD LegacyID INT
GO
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'A', Name, ID
FROM TableA
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableAChild AC
JOIN TableA A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'A'
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'B', Name, ID
FROM TableB
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableBChild AC
JOIN TableB A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'B'
ALTER TABLE TableC DROP COLUMN LegacyID
GO
You can use a map table to link the old and new ids together based on some key.
In my example, I am using the order of insertion into TableC.
Create a map table with an identity column.
Add data in TableC table based on order of ID of TableA and get the inserted ids in the map
Use the same order of TableA.id to get a ROWNUMBER() and match it with the identity column of the map table and update the old_id in map to match TableA.id with TableC.id .
Use the map to insert into the TableCChild table
Truncate the map and rinse and repeat for other tables.
Sample Query
CREATE TABLE #map(id int identity,new_id int,old_id int);
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'A',Name
FROM TableA
ORDER BY ID
update m
set m.old_id = ta.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableA
)ta on ta.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableAChild TA ON M.old_id = TA.Parent
TRUNCATE TABLE #map
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'B',Name
FROM TableB
ORDER BY ID
update m
set m.old_id = tb.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableB
)tb on tb.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableBChild TB ON M.old_id = TB.Parent
DROP TABLE #Map
I just wrote the following SQL to do it if the Name is unique in TableA and unique in TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.Name = a.Name
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.Name = b.Name
AND tc.TableType = 'B'
If Name is not unique and only the ID is the Unique Identifier then I would add the LegacyId as suggested and the code would then be as follows
/* Change Table C to Have LegacyId as well and this is used to find the New Key for Inserts
CREATE TABLE TableC
(
ID INT NOT NULL IDENTITY PRIMARY KEY,
TableType VARCHAR(1),
LegacyId INT,
NAME VARCHAR(30)
);
*/
INSERT INTO TableC (Name, TableType, LegacyId)
SELECT DISTINCT NAME,
'A',
Id
FROM TableA
UNION
SELECT DISTINCT NAME,
'B',
Id
FROM TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.LegacyId = a.Id
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.LegacyId = b.Id
AND tc.TableType = 'B'
We can reach this by turning the Identity column off till we finish the insertion like the following example.
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID, 'A', Name FROM TableA
INSERT INTO TableCChild(Parent, Name)
SELECT Parent, Name FROM TableAChild
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM TableC
PRINT #MAXID
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID + #MAXID, 'B', Name FROM TableB
SET IDENTITY_INSERT TableC OFF
INSERT INTO TableCChild(Parent, Name)
SELECT Parent + #MAXID, Name FROM TableBChild
SET IDENTITY_INSERT TableC OFF
SELECT * FROM TableC
SELECT * FROM TableCChild
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
If you need to insert records in third table TableC and TableCChild for later use then it's fine to insert data in these tables but if you only need this table data to use it in your stored procedure for the time being then you can also just work with first two tables to get the desired result.
select * from (
select a.ID,'A' as TableType,a.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select a.ID,'B' as TableType,a.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableC
Similarly get TableCChild
select * from
(
select b.ID,b.Parent,b.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select b.ID,b.Parent,b.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableCChild
And if you have to insert in TableC and TableCChild then you have to recreate TableC with primary key on ID and TableType, and turn off the identity for ID column.

How to use different sub queries with SQL MERGE

Can we pass different sub queries in SQL MERGE for inserting and updating data?
MERGE TableA AS SOURCE
USING TbaleB AS TARGET
ON (SOURCE.ID=TARGET.ID)
WHEN NOT MATCHED BY TARGET
THEN INSERT(COLUMN1, COLUMN2,COLUMN3 )
SELECT * FROM TableC
WHEN MATCHED
THEN UPDATE COLUMN1=SOURCE.Column1, COLUMN2=SOURCE.Column2,COLUMN3=SOURCE.Column3
FROM Table4
INNER JOIN INNER JOIN Table5
ON Table4.ID=Table5.ID
WHERE Table5.ID=1
OUTPUT $action, inserted.*;
Is there any other option to do this?
EDIT:
Using below script to create tables, insert data,
CREATE TABLE TableA([ID] [int] IDENTITY(1,1) NOT NULL,
ColumnA [nvarchar](50) NULL,
ColumnB [nvarchar](50) NULL,
ColumnC [nvarchar](50) NULL,
) ON [PRIMARY]
CREATE TABLE TableB([ID] [int] IDENTITY(1,1) NOT NULL,
ColumnA [nvarchar](50) NULL,
ColumnB [nvarchar](50) NULL,
ColumnC [nvarchar](50) NULL,
) ON [PRIMARY]
Insert into TableA values('A','1','W')
Insert into TableA values('A','2','X')
Insert into TableA values('B','1','Y')
Insert into TableB values('A','1','U')--To be update
Insert into TableB values('B','2','N')--New row to insert
Used below query to insert:
SELECT Source.* INTO #tempTable
FROM (SELECT row_number() OVER ( PARTITION BY ColumnA,ColumnB ORDER BY ColumnA,ColumnB ) Row_ID, * --using row_number to remove duplicate rows
FROM TableB) Source
LEFT OUTER JOIN TableA Target
ON Source.ColumnA = Target.ColumnA AND Source.ColumnB = Target.ColumnB
WHERE Row_ID=1 AND Target.ColumnB IS NULL AND Target.ColumnB IS NULL
ALTER TABLE #tempTable drop column Row_ID, ID
INSERT INTO TableA(ColumnA,ColumnB ,ColumnC)
select * from #tempTable
Used below query to update existing record:
UPDATE Target SET Target.ColumnC =Source.ColumnC
FROM TableA Target
INNER JOIN TableB AS Source
ON Source.ColumnA = Target.ColumnA AND Target.ColumnB = SOURCE.ColumnB
And I need the output as
ID ColumnA ColumnB ColumnC
4 A 1 U
5 A 2 X
6 B 1 Y
7 B 2 N
It is working fine, but for performance perpose, can we do the same by using MERGE?
Try the following:
WITH S AS
(
SELECT
B.ColumnA, B.ColumnB, B.ColumnC
FROM
(
SELECT
B.ColumnA, B.ColumnB, B.ColumnC,
ROW_NUMBER() OVER (PARTITION BY B.ColumnA, B.ColumnB ORDER BY B.ColumnA, B.ColumnB) AS RowId
FROM TableB B
) B
WHERE
B.RowId = 1
)
MERGE
TableA T
USING
S ON T.ColumnA = S.ColumnA AND T.ColumnB = S.ColumnB
WHEN NOT MATCHED BY TARGET
THEN INSERT (ColumnA, ColumnB, ColumnC)
VALUES (S.ColumnA, S.ColumnB, S.ColumnC)
WHEN MATCHED AND
(S.ColumnC <> T.ColumnC OR S.ColumnC IS NULL AND T.ColumnC IS NOT NULL OR S.ColumnC IS NOT NULL AND T.ColumnC IS NULL)
THEN UPDATE SET T.ColumnC = S.ColumnC;

"Invalid Column" when using column from table variable

I'm trying to declare a table variable and then join it to a table I created in the database. Every time I try to insert my "NAME" field into my table, I get the error 'Invalid Column Name "NAME"', even though the GNAME field works fine. What am I doing wrong, and how can I join me NAME column?
DECLARE #Names TABLE
(
ID INT,
NAME VARCHAR(100),
GNAME VARCHAR(100)
)
INSERT INTO #Names
(
ID,
NAME,
GNAME
)
SELECT
CName.ID,
Ref.NAME,
Ref.GNAME
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.ID = Ref.ID
IF ( OBJECT_ID('dbo.ReportTable', 'U') IS NOT NULL)
DROP TABLE dbo.ReportTable
CREATE TABLE [dbo].[ReportTable]
(
[ID_NUMBER] [INT],
[NAME] [VARCHAR](150)
[GNAME] [VARCHAR](150)
)
INSERT INTO [dbo].[ReportTable]
(
ID_NUMBER,
NAME,
GNAME
)
SELECT
C.ID_NUMBER,
N.NAME,
N.GNAME
FROM
#Names AS N
INNER JOIN
#CurrentPositions AS C
ON N.ID_NUMBER = C.ID_NUMBER
Try using a Temp table :
CREATE TABLE #Names
(
ID INT,
NAME VARCHAR(100),
GNAME VARCHAR(100)
)
INSERT INTO #Names
(
ID,
NAME,
GNAME
)
SELECT
CName.ID,
Ref.NAME,
Ref.GNAME
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.ID = Ref.ID
IF ( OBJECT_ID('dbo.ReportTable', 'U') IS NOT NULL)
DROP TABLE dbo.ReportTable
CREATE TABLE [dbo].[ReportTable]
(
[ID_NUMBER] [INT],
[NAME] [VARCHAR](150)
[GNAME] [VARCHAR](150)
)
INSERT INTO [dbo].[ReportTable]
(
ID_NUMBER,
NAME,
GNAME
)
SELECT
C.ID_NUMBER,
N.NAME,
N.GNAME
FROM
#Names AS N
INNER JOIN
#CurrentPositions AS C
ON N.ID_NUMBER = C.ID_NUMBER
I've assumed that you will also change the table variable #CurrentPositions to a temp table
Just remember to drop the tables after you use them.
It is quite possible that all you need to do is wrap your field names in square brackets, e.g.
INSERT INTO #Names
(
[ID],
[NAME],
[GNAME]
)
SELECT
CName.[ID],
Ref.[NAME],
Ref.[GNAME]
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.[ID] = Ref.[ID]
If that doesn't fix it, please post the schema of your #CurrentPositions and dbo.NameField tables.

How to INSERT using an inverse JOIN on multiple keys?

How do I do an inverse join with more than one key column?
In this baby-toy SqlServer example, I have the following
CREATE TABLE [dbo].[CarList](
[myID] [int] IDENTITY(1,1) NOT NULL,
[CarColour] [varchar](32) NOT NULL,
[CarName] [varchar](128) NOT NULL,
[CarCompany] [varchar](32) NOT NULL,
CONSTRAINT [PK_CarList] PRIMARY KEY CLUSTERED(
[myID] ASC,
[CarColour] ASC,
[CarName] ASC,
[CarCompany] ASC
)
)
GO
INSERT INTO CarList (CarColour, CarName, CarCompany)
VALUES('blue', 'Abe', 'Ford')
Elsewhere in the DB I have a table like
CREATE TABLE [dbo].[NewCars](
[CarColour] [varchar](32) NOT NULL,
[CarName] [varchar](128) NOT NULL,
[CarCompany] [varchar](32) NOT NULL,
)
GO
INSERT INTO NewCars (CarColour, CarName, CarCompany)
SELECT 'blue', 'Abe', 'Ford'
UNION ALL
SELECT 'blue', 'Abe', 'GM'
UNION ALL
SELECT 'blue', 'Betty', 'Ford'
UNION ALL
SELECT 'green', 'Abe', 'Honda'
Now I want to insert cars I don't already have in the CarList table
Something like...
INSERT INTO CarList ( CarColour, CarName, CarCompany)
SELECT DISTINCT new.CarColour, new.CarName, new.CarCompany
FROM NewCars new, CarList old
WHERE new.CarColour <> old.CarColour
AND new.CarName <> old.CarName
AND new.CarCompany <> old.CarCompany
Which doesn't work because the "blue', 'Betty', 'Ford' row will get filtered out...
If this were just a single ID of some kind it would be really easy
INSERT INTO myTable (myID, param1, param2, etc)
SELECT param1, param2, etc
FROM someOtherTable new
WHERE new.myID NOT IN (SELECT myID FROM myTable)
For reasons I don't really want to get into, I cannot remove rows from NewCars that match CarList. I also need to do this in one pass if possible.
[edit]
Thanks guys!
thanks for DDL and DML
Here is one way
INSERT INTO CarList ( CarColour, CarName, CarCompany)
SELECT DISTINCT *
FROM NewCars n
where not exists (select 1 from CarList c where c.CarColour =n.CarColour
and c.CarName = n.CarName
and c.CarCompany = n.CarCompany)
There are at least 4 different way to do this
NOT IN (will not work for more than 1 column like you have)
NOT EXISTS
LEFT and RIGHT JOIN
OUTER APPLY (2005+)
EXCEPT (2005+)
Read Select all rows from one table that don't exist in another table
INSERT
INTO CarList ( CarColour, CarName, CarCompany)
SELECT CarColour, CarName, CarCompany
FROM NewCars nc
WHERE NOT EXISTS
(
SELECT 1
FROM CarList cl
WHERE cl.CarColor = nc.CarColor
AND cl.CarName = nc.CarName
AND cl.CarCompany = nc.CarCompany
)
I would probably use:
INSERT INTO CarList(CarColour, CarName, CarCompany)
SELECT
NC.CarColour,
NC.CarName,
NC.CarCompany
FROM
NewCars NC
LEFT OUTER JOIN CarList CL ON
CL.CarColour = NC.CarColour AND
CL.CarName = NC.CarName AND
CL.CarCompany = NC.CarCompany
WHERE
CL.MyID IS NULL
INSERT INTO CarList ( CarColour, CarName, CarCompany)
SELECT DISTINCT new.CarColor, new.CarName, new.CarCompany
FROM NewCar new
where not exists (select 0
from CarList old
WHERE new.CarColour = old.CarColour
AND new.CarName = old.CarName
AND new.CarCompany = old.CarCompany)
--This statement matches all that does exists in carlist
--and insert everything that does not exists in Carlist