Related
I need to build XML in SQL Server that has this format. You can see there are two XMLNAMESPACES on the first line but there is a third one further down next to Location.
<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypes">
<stuff>
<Description>blue</Description>
<Location xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues">
<d3p1:Code>64</d3p1:Code>
<d3p1:Description>Balloons</d3p1:Description>
</Location>
</stuff>
</arrayofstuff>
Here is what I have so far, with some sample data. It looks like there is a nested for XML query within the first query, but I can't seem to use the WITH statement a second time since it has to be the first command in a batch, so I'm not sure what to do.
IF EXISTS(SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('myTable'))
BEGIN;
DROP TABLE [myTable];
END;
GO
CREATE TABLE [myTable] (
[myTableID] INTEGER NOT NULL IDENTITY(1, 1),
[Description] VARCHAR(MAX) NULL,
[sourceID] INTEGER NOT NULL ,
[Location] VARCHAR(255) NULL,
[Code] VARCHAR(255) NULL,
[Location_Desc] VARCHAR(255) NULL,
PRIMARY KEY ([myTableID])
);
GO
INSERT INTO myTable([SourceID],[Description],[Location],[Code],[Location_Desc])
VALUES(3,'yellow','Oxford County','64','list'),
(3,'blue','Fraser Lake','64','list'),
(2,'red','San Marcello Pistoiese','64','list'),
(2,'green','Gembloux','64','list'),
(2,'green','Yeongcheon','64','list')
GO
WITH XMLNAMESPACES (default 'http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess', 'http://www.w3.org/2001/XMLSchema-instance' as i )
SELECT
[sourceID]
,cast(stuff((
SELECT
[Description] as [Description]
,[Code] AS [Location/Code]
,[Location_Desc] AS [Location/Description]
FROM [myTable] mnbm
where mnbm.[sourceID] = p.[sourceID]
for xml path('stuff'), root ('arrayofstuff')
),1,0,'') as xml) as Ids
from [myTable] p
group by
p.[sourceID]
Here is the result of my output currently:
<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess">
<stuff>
<Description>commodo</Description>
<Location>San Marcello Pistoiese</Location>
</stuff>
<stuff>
<Description>ipsum</Description>
<Location>Gembloux</Location>
</stuff>
<stuff>
<Description>ipsum</Description>
<Location>Yeongcheon</Location>
</stuff>
</arrayofstuff>
Is there some specific reason why xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues" has to appear on the Location element? Namespaces can be defined anywhere in an XML document, so long as they're defined before they're referenced, so you can define it on the root element as part of WITH XMLNAMESPACES, e.g.:
drop table if exists dbo.myTable;
create table dbo.myTable (
myTableID integer not null identity(1, 1),
[Description] varchar(max) null,
sourceID integer not null,
[Location] varchar(255) null,
Code varchar(255) null,
Location_Desc varchar(255) null,
primary key (myTableID)
);
insert into dbo.myTable (sourceID,[Description],[Location],Code,Location_Desc)
values (1, 'blue', 'Somewhere', '64', 'Balloons');
with xmlnamespaces (
default 'http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess',
'http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues' as d3p1,
'http://www.w3.org/2001/XMLSchema-instance' as i )
select
[sourceID],
cast((
select
[Description],
Code as [Location/d3p1:Code],
Location_Desc as [Location/d3p1:Description]
from dbo.myTable mnbm
where mnbm.sourceID = p.sourceID
for xml path('stuff'), root('arrayofstuff')
) as xml) as Ids
from dbo.myTable p
group by p.sourceID;
Which yields:
<arrayofstuff
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues"
xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess">
<stuff>
<Description>blue</Description>
<Location>
<d3p1:Code>64</d3p1:Code>
<d3p1:Description>Balloons</d3p1:Description>
</Location>
</stuff>
</arrayofstuff>
You can try the following solution based on XQuery and FLWOR expression.
It is producing XML that is shaped exactly as the desired output.
It is a two step process:
Compose raw XML.
Shape raw XML with namespaces based on the desired output.
SQL
-- DDL and sample data population, start
DECLARE #myTable TABLE
(
[myTableID] INTEGER NOT NULL IDENTITY(1, 1),
[Description] VARCHAR(MAX) NULL,
[sourceID] INTEGER NOT NULL,
[Location] VARCHAR(255) NULL,
[Code] VARCHAR(255) NULL,
[Location_Desc] VARCHAR(255) NULL,
PRIMARY KEY ([myTableID])
);
INSERT INTO #myTable
(
[sourceID],
[Description],
[Location],
[Code],
[Location_Desc]
)
VALUES
(3, 'yellow', 'Oxford County', '64', 'list'),
(3, 'blue', 'Fraser Lake', '64', 'list'),
(2, 'red', 'San Marcello Pistoiese', '64', 'list'),
(2, 'green', 'Gembloux', '64', 'list'),
(2, 'green', 'Yeongcheon', '64', 'list');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT [sourceID]
, (SELECT [Description] AS [Description]
, [Code] AS [Code]
, [Location_Desc] AS [Location_Desc]
FROM #myTable AS mnbm
WHERE mnbm.[sourceID] = p.[sourceID]
FOR XML PATH('stuff'), TYPE, ROOT('arrayofstuff')
) AS Ids
FROM #myTable AS p
GROUP BY p.[sourceID]
)
SELECT rs.sourceID, rs.Ids AS [Before]
, rs.Ids.query('<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypes">
{
for $x in /*:arrayofstuff/*:stuff
return <stuff>
<Description>{data($x/*:Description)}</Description>
<Location xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues">
<d3p1:Code>{data($x/*:Code)}</d3p1:Code>
<d3p1:Description>{data($x/*:Location_Desc)}</d3p1:Description>
</Location>
</stuff>
}
</arrayofstuff>') AS [After]
FROM rs;
I have this table structure and I want to write Insert Query that'll insert data into the table from the values provided in parameters
CREATE TABLE [dbo].[EMPLOYEE](
[ID] [int] NULL,
[EMPLOYEE_NAME] [varchar](50) NULL,
[DEPARTMENT_ID] [int] NULL,
) ON [PRIMARY]
DECLARE #ID VARCHAR(20) = '1, 2';
DECLARE #Name VARCHAR(50) = 'Asim Asghar, Ahmad'
DECLARE #DeptID VARCHAR(20) = '5, 12';
INSERT INTO EMPLOYEE VALUES (#ID, #Name, #DeptID)
Based on the data provided above it should add 4 rows with following data
1 Asim Asghar 5
2 Ahmad 5
1 Asim Asghar 12
2 Ahmad 12
Hope someone can help
You can not pass multiple values together through a variable at a time. The script should be as below considering one person at a time-
CREATE TABLE [dbo].[EMPLOYEE](
[ID] [int] NULL,
[EMPLOYEE_NAME] [varchar](50) NULL,
[DEPARTMENT_ID] [int] NULL,
) ON [PRIMARY]
DECLARE #ID INT = 1;
DECLARE #Name VARCHAR(50) = 'Asim Asghar';
DECLARE #DeptID INT = 5;
INSERT INTO EMPLOYEE(ID,EMPLOYEE_NAME,DEPARTMENT_ID) VALUES (#ID, #Name, #DeptID)
Then you can change the values for next person and execute the INSERT script again. And from the second execution, you have to skip the Table creation script other wise it will through error.
The question's query is trying to insert a single row, using strings values for the ID and DeptID fields. This will fail with a runtime error.
One can use the table value constructor syntax to insert multiple rows in a single INSERT statement :
INSERT INTO EMPLOYEE
VALUES
(1, 'Asim Asghar', 5),
(2, 'Ahmad', 5),
(1, 'Asim Asghar', 12),
(2, 'Ahmad', 12)
The values can come from parameters or variables.
Using duplicate IDs and names in an Employee table hints at a problem. Looks like the intent is to store employees and their department assignments. Otherwise why insert 4 rows instead of 8 with all possible combinations?
Employee should be changed to this :
CREATE TABLE [dbo].[EMPLOYEE]
(
[ID] [int] primary key not null,
[EMPLOYEE_NAME] [varchar](50)
)
And another table, EmployeeAssignment should be added
CREATE TABLE [dbo].[EMPLOYEE_ASSIGNMENT]
(
Employee_ID int not null FOREIGN KEY REFERENCES EMPLOYEE(ID),
[DEPARTMENT_ID] [int] not NULL,
PRIMARY KEY (Employee_ID,Department_ID)
)
The data can be inserted with two INSERT statements :
INSERT INTO EMPLOYEE
VALUES
(1, 'Asim Asghar'),
(2, 'Ahmad'),
INSERT INTO EMPLOYEE_ASSIGNMENT
VALUES
(1, 5),
(2, 5),
(1, 12),
(2, 12)
Try this, You need this function for splitting by char using dynamic delimiter.
CREATE FUNCTION UDF_SPLIT_BY_CHAR(#STRING VARCHAR(8000), #DELIMITER CHAR(1))
RETURNS #TEMPTABLE TABLE (S_DATA VARCHAR(8000))
AS
BEGIN
DECLARE #IDX INT=1,#SLICE VARCHAR(8000)
IF LEN(#STRING)<1 OR #STRING IS NULL RETURN
WHILE #IDX<> 0
BEGIN
SET #IDX = CHARINDEX(#DELIMITER,#STRING)
IF #IDX!=0
SET #SLICE = LEFT(#STRING,#IDX - 1)
ELSE
SET #SLICE = #STRING
IF(LEN(#SLICE)>0)
INSERT INTO #TEMPTABLE(S_DATA) VALUES(#SLICE)
SET #STRING = RIGHT(#STRING,LEN(#STRING) - #IDX)
IF LEN(#STRING) = 0 BREAK
END
RETURN
END
Declare #EMPLOYEE TABLE
(
[ID] [int] NULL,
[EMPLOYEE_NAME] [varchar](50) NULL,
[DEPARTMENT_ID] [int] NULL
)
DECLARE #ID VARCHAR(20) = '1, 2'
,#Name VARCHAR(50) = 'Asim Asghar, Ahmad'
,#DeptID VARCHAR(20) = '5, 12';
insert into #EMPLOYEE
(
[ID],[EMPLOYEE_NAME],[DEPARTMENT_ID]
)
Select a.S_DATA,b.S_DATA,c.S_DATA
from dbo.UDF_SPLIT_BY_CHAR(#id,',') a
left join dbo.UDF_SPLIT_BY_CHAR(#Name,',') b on 1=1
left join dbo.UDF_SPLIT_BY_CHAR(#DeptID,',') c on 1=1
create database staff_management;
use staff_management;
create table Employee
(
eID int(100) NOT NULL IDENTITY(1,1) PRIMARY KEY,
eName varchar(255) NOT NULL,
Job text NOT NULL,
Salary int(100) NOT NULL,
Comm int(100),
hDate date NOT NULL,
dID int(10) NOT NULL,
constraint emp_pk primary key (eID)
);
alter table Employee IDENTITY(1,1) PRIMARY KEY=1001;
alter table Employee
add column Mgr int(100) after eName;
insert into Employee(eName,Mgr, Job, Salary, Comm, hDate, dID)
values( "ken Adams", 1004, "Salesman", 70000, 20000, "2008-04-12", 1),
("Ru Jones", 1004, "Salesman", 65000, 15000, "2010-01-18", 1),
( "Dhal Sim", 1006, "Accountant", 88000, NULL, "2001-03-07", 2),
( "Ellen Honda", 1006, "Manager", 118000, NULL, "2001-03-17", 1),
( "Mike Bal", 1006, "Receptionist", 68000, NULL, "2006-06-21", 3),
( "Martin Bison",NULL, "CEO", 210000, NULL, "2010-07-12", 3),
( "Shen Li", 1004, "Salesman", 86000, 18000, "2014-09-18", 1),
( "Zang Ross", 1004, "Salesman", 65000, 10000, "2017-02-02", 1),
( "Sagar Kahn", 1004, "Salesman", 70000, 15000, "2016-03-01", 1);
alter table Employee
add constraint emp_mgr_fk foreign key (Mgr) references Employee(eID) on update cascade on delete set NULL;
create table Department
(
dID int(10) NOT NULL unique IDENTITY(1,1) PRIMARY KEY,
dName varchar(255) not null,
Address text,
phone text,
constraint d_pk primary key (dID)
);
alter table Employee
add constraint emp_d_fk
foreign key (dID) references Department(dID);
create table Grade
(
gID char(10) not null unique,
MinSal int(100),
MaxSal int(100),
Leavee int(10),
constraint g_pk primary key (gID)
);
INSERT INTO Grade (gID, MinSal, MaxSal, Leavee)
VALUES ('A', NULL, 60000, 20),
('B', 60000, 80000, 20),
('C', 80000, 100000, 20),
('D', 100000, 120000, 25),
('E', 120000, NULL, 30);
select * from Grade;
insert into Department (dName, Address, phone)
values("Sales", "Sydney", "0425 198 053"),
("Accounts", "Melbourne", "0429 198 955"),
("Admin", "Melbourne", "0428 198 758"),
("Marketing", "Sydney", "0427 198 757");
select * from Department;
I'm issue with my code
Msg 156, Level 15, State 1, Line 18
Incorrect syntax near the keyword 'IDENTITY'.
Msg 156, Level 15, State 1, Line 21
Incorrect syntax near the keyword 'column'.
The syntax for SQL Server is NOT auto_increment - you need to use an INT IDENTITY column instead. And also: in T-SQL an INT is an INT is an INT - no "precision" can be defined):
Instead of this:
create table Employee
(
eID int(100) NOT NULL auto_increment,
use this:
CREATE TABLE dbo.Employee
(
eID INT NOT NULL IDENTITY(1,1),
This question is posted under SQL-Server which is Microsoft not MySQL but your syntax appears to be for MySQL.
If you are running MSSQL the code below will work but you need to look at your foreign keys as you are trying to make a foreign key for a column on the same table. Normally when a key is introduced it is in relation to another table. I.E.the FK on Grade references the PK on Employee.
create database staff_management;
use staff_management;
create table Employee
(
eID int NOT NULL IDENTITY(1,1) PRIMARY KEY,
eName varchar(255) NOT NULL,
Job text NOT NULL,
Salary int NOT NULL,
Comm int,
hDate date NOT NULL,
dID int NOT NULL,
);
alter table Employee
add Mgr int;
insert into Employee(eName,Mgr, Job, Salary, Comm, hDate, dID)
values ('ken Adams', 1004, 'Salesman', 70000, 20000, '2008-04-12', 1),
('Ru Jones', 1004, 'Salesman', 65000, 15000, '2010-01-18', 1),
('Dhal Sim', 1006, 'Accountant', 88000, NULL, '2001-03-07', 2),
('Ellen Honda', 1006, 'Manager', 118000, NULL, '2001-03-17', 1),
('Mike Bal', 1006, 'Receptionist', 68000, NULL, '2006-06-21', 3),
('Martin Bison',NULL, 'CEO', 210000, NULL, '2010-07-12', 3),
('Shen Li', 1004, 'Salesman', 86000, 18000, '2014-09-18', 1),
('Zang Ross', 1004, 'Salesman', 65000, 10000, '2017-02-02', 1),
('Sagar Kahn', 1004, 'Salesman', 70000, 15000, '2016-03-01', 1);
--alter table Employee
--add constraint emp_mgr_fk
-- foreign key (Mgr) references Employee(eID)
-- on update cascade on delete set NULL;
create table Department
(
dID int NOT NULL IDENTITY(1,1) PRIMARY KEY,
dName varchar(255) not null,
Address text,
phone text,
);
--alter table Employee
--add constraint emp_d_fk
--foreign key (dID) references Department(dID);
create table Grade
(
gID char(10) not null unique,
MinSal int,
MaxSal int,
Leavee int,
constraint g_pk primary key (gID)
);
INSERT INTO Grade (gID, MinSal, MaxSal, Leavee)
VALUES ('A', NULL, 60000, 20),
('B', 60000, 80000, 20),
('C', 80000, 100000, 20),
('D', 100000, 120000, 25),
('E', 120000, NULL, 30);
select * from Grade;
insert into Department (dName, Address, phone)
values ('Sales', 'Sydney', '0425 198 053'),
('Accounts', 'Melbourne', '0429 198 955'),
('Admin', 'Melbourne', '0428 198 758'),
('Marketing', 'Sydney', '0427 198 757');
select * from Department;
I have this table structure and the sample data as well. I want to get only one row of the data. But instead it is giving me rows equal to it's child records.
--DROP TABLE [Detail];
--DROP TABLE [Master];
--CREATE TABLE [Master]
--(
--ID INT NOT NULL PRIMARY KEY,
--Code VARCHAR(25)
--);
--INSERT INTO [Master] VALUES (1, 'CASH');
--INSERT INTO [Master] VALUES (2, 'CASH');
--CREATE TABLE [Detail]
--(
--ID INT NOT NULL PRIMARY KEY,
--MasterID INT,
--DrAmount Numeric,
--CrAmount Numeric,
--CONSTRAINT FK_MASTER FOREIGN KEY (MasterID)
--REFERENCES [Master](ID)
--);
--INSERT INTO [Detail] VALUES (1, 1, '2200', NULL);
--INSERT INTO [Detail] VALUES (2, 1, NULL, '3200');
--INSERT INTO [Detail] VALUES (3, 1, '1000', NULL);
--INSERT INTO [Detail] VALUES (4, 2, NULL, '3200');
--INSERT INTO [Detail] VALUES (5, 2, '3200', NULL);
Here is the query and result:
SELECT [MASTER].[Code], [DETAIL].[MasterID], [DETAIL].[CrAmount]
FROM [MASTER], [DETAIL]
WHERE [MASTER].[ID] = [DETAIL].[MasterID]
Looks like you need GROUP BY and as #HoneyBadger suggests, it would be better to use the modern explicit join syntax - it is much more clear:
select m.code, d.masterid, sum(d.cramount) amount
from [master] m
join[detail] d on m.[id] = d.[masterid]
group by m.code, d.masterid
Result:
code masterid amount
CASH 1 3200
CASH 2 3200
I have various offices and one central head office. Each office has its own SQL Server 2008 instance so each office has its own data set with its own set of IDs.
Each office has already imported data into the head office and stored the data on a set of STAGING_Tables that look like this.
DECLARE #STAGING_COUNTRY TABLE
(
Original_CountryID INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
Data VARCHAR(200) NOT NULL
);
DECLARE #STAGING_CITY TABLE
(
Original_CityID INT NOT NULL,
Original_CountryID_FK INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
OtherData VARCHAR(100) NOT NULL
);
STAGING_COUNTRY has the original ID of each row (which off course will be duplicated since each office will have ID=1 for the 1st row on their Country table) and also has a unique OfficeID value that together with the Original_CountryID ..makes a unique value.
STAGING_CITY has also the original ID of each row, the unique OfficeID value that represent each office and in this case a FK to CountryID, (but of course at this point we have a reference to the Original_CountryID ..that in conjunction with the office ID could be identified).
Let's add some dummy rows:
/* ADD DUMMY VALUES TO STAGING_COUNTRY */
INSERT INTO #STAGING_COUNTRY
(Original_CountryID, OfficeID, Data) VALUES (1, 'Office1', 'USA')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (2, 'Office1', 'Canada')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (3, 'Office1', 'Japan')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (1, 'Office2', 'USA')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (1, 'Office2', 'Italy')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (3, 'Office2', 'Canada')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (3, 'Office3', 'Canada')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (2, 'Office3', 'France')
INSERT INTO #STAGING_COUNTRY (Original_CountryID, OfficeID, Data)
VALUES (3, 'Office3', 'USA')
/* ADD DUMMY VALUES TO STAGING_CITY */
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK, OfficeID, OtherData) VALUES
(1, 1, 'Office1', 'New York')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (2, 1, 'Office1', 'Vancouver')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (3, 1, 'Office1', 'Tokia')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (1, 2, 'Office2', 'New York')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (2, 2, 'Office2', 'Rome')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (3, 2, 'Office2', 'Vancouver')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (1, 3, 'Office3', 'Vancouver')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (2, 3, 'Office3', 'Paris')
INSERT INTO #STAGING_CITY (Original_CityID, Original_CountryID_FK,
OfficeID, OtherData) VALUES (3, 3, 'Office3', 'New York')
The central head office wants to run reports from a central dtabase that pretty much contains copy all the data from all offices but in order to make this reporting DB optimized, we need to reshuffle a bit the STAGING_Tables ...and reorganize the data in FINAL_Tables that look like this:
DECLARE #FINAL_COUNTRY TABLE
(
CountryID INT IDENTITY PRIMARY KEY,
Original_CountryID INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
Data VARCHAR(200) NOT NULL
);
DECLARE #FINAL_CITY TABLE
(
CityID INT IDENTITY PRIMARY KEY,
Original_CityID INT NOT NULL,
CountryID_FK INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
OtherData VARCHAR(100) NOT NULL
);
PROBLEM:
The FINAL_COUNTRY and FINAL_CITY tables should be as optimized as possible for reporting purposes. These reports will be written in T-SQL stored procedures.
QUESTION:
What is the best way to reorganize the FINAL_Tables so that each record has a TRUE PK identifier (like in the original Office_Tables) and each FK is updated to point to the right newly created PK ...at the server level?
NOTE:
Please note that both staging & final tables are inside the same DB, on the server.
Also we still need to keep the OriginalIDs on the FINAL_Tables for other purposes.
GOALS:
The main goal here is to reorganize into a set of tables that can be easily indexed for performance purposes.
Please ask more info if needed.
Many many thanks in advanced...
This is probably just a partial answer. You may want to consider putting a generic IDENTITY id on each of your staging tables. Something like:
DECLARE #STAGING_COUNTRY TABLE
(
Stage_Country_id INT IDENTITY(1,1) NOT NULL,
Original_CountryID INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
Data VARCHAR(200) NOT NULL
);
DECLARE #STAGING_CITY TABLE
(
Stage_City_id INT IDENTITY(1,1) NOT NULL,
Original_CityID INT NOT NULL,
Original_CountryID_FK INT NOT NULL,
OfficeID VARCHAR(10) NOT NULL,
OtherData VARCHAR(100) NOT NULL
);
Your final tables should not have the original_ids as you should only have 1 record per city / country in them.
Then I think you'd need some sort of cross reference tables to bridge your final tables to your stage tables. That would look like this:
DECLARE #COUNTRY_xref TABLE
(
country_xref_id INT IDENTITY(1,1) not null,
CountryID INT not null,
Stage_Country_id INT
);
DECLARE #CITY_xref TABLE
(
city_xref_id INT IDENTITY(1,1) not null,
CityID INT not null,
Stage_City_id INT not null
);
Are you also asking what the loading / conversion process would look like or was this more about the schema?
your final tables would probably look like this:
DECLARE #FINAL_COUNTRY TABLE
(
CountryID INT IDENTITY PRIMARY KEY,
Data VARCHAR(200) NOT NULL
);
DECLARE #FINAL_CITY TABLE
(
CityID INT IDENTITY PRIMARY KEY,
CountryID_FK INT NOT NULL,
OtherData VARCHAR(100) NOT NULL
);