Хорошо, я точно не знаю, где вы боретесь, поэтому вот сценарий, который делает то, что вы просили. Ничего из этого не является слишком сложным для отслеживания, поэтому, возможно, проведите сканирование, а затем дайте мне знать, какие биты сбивают с толку?
Настройка структуры таблицы:
CREATE TABLE tempDataTable (
TempProductId INT,
TempProductUrl VARCHAR(512),
TempProductPrice VARCHAR(50),
TempProductPricePerUnit VARCHAR(50),
TempProductName VARCHAR(512));
INSERT INTO tempDataTable SELECT 2491, 'https://yadayada1', '£1.65/unit', '46p/100g', 'Yeo Valley Little Yeos, blah';
INSERT INTO tempDataTable SELECT 2492, 'https://yadayada2', '60p/unit', '1p/ea', 'Sainsbury''s Little Ones, etc';
CREATE TABLE Product (
ProductId INT PRIMARY KEY,
ProductName VARCHAR(512),
ProductUrl VARCHAR(512));
CREATE TABLE ProductPricing (
ProductPricingId INT IDENTITY(1,1) PRIMARY KEY,
ProductId INT,
ProductPrice VARCHAR(50),
ProductPricePerUnit VARCHAR(50),
ProductPricingDate DATETIME);
ALTER TABLE ProductPricing ADD CONSTRAINT foreignkey$ProductPricing$Product FOREIGN KEY (ProductId) REFERENCES Product (ProductId);
Это дает Мне нужно играть с тремя таблицами, одна с некоторыми временными данными, и две, в которые вы хотите поместить sh данные, с парой первичных ключей и ограничением внешнего ключа для обеспечения целостности между двумя таблицами.
Хорошо, пока?
Теперь разделить данные между двумя таблицами так же просто, как:
INSERT INTO Product (ProductId, ProductName, ProductUrl) SELECT TempProductId, TempProductName, TempProductUrl FROM tempDataTable;
INSERT INTO ProductPricing (ProductId, ProductPrice, ProductPricePerUnit, ProductPricingDate) SELECT TempProductId, TempProductPrice, TempProductPricePerUnit, GETDATE() FROM tempDataTable;
Если вы запустите это, вы должны получить данные в две ваши таблицы, например:
Product
ProductId ProductName ProductUrl
2491 Yeo Valley Little Yeos, blah https://yadayada1
2492 Sainsbury's Little Ones, etc https://yadayada2
ProductPricing
ProductPricingId ProductId ProductPrice ProductPricePerUnit ProductPricingDate
1 2491 £1.65/unit 46p/100g 2020-04-27 14:29:14.657
2 2492 60p/unit 1p/ea 2020-04-27 14:29:14.657
Теперь есть целый ряд вопросов, которые возникают из этого:
- как вы собираетесь справиться с выполнением этого более одного раза, потому что при втором запуске будут нарушения первичного ключа?
- хотите ли вы как-то очистить временные данные при успешном завершении? ?
- ты ва? Не использовать системную дату в качестве даты ценообразования, или на вашем изображении больше столбцов?
- Вы хотите проверить данные на наличие дубликатов и обработать их перед запуском сценария, иначе просто потерпите неудачу?
- если вы получили дубликат, пропускаете ли вы или обновляете данные (
MERGE
)? - почему вы хотите, чтобы это было хранимой процедурой? Я имею в виду, что сделать это достаточно просто, но я не понимаю, почему это должно было бы повторяться ... в любом случае, не видя других «движущихся частей» в этой системе.
I ' Я предполагаю, что вы загружаете объемные данные во временную таблицу каким-либо образом, из книги Excel, или XML, или подобным образом. Поэтому все, что вам нужно, это способ «разбить данные» на несколько таблиц. Если это действительно так, то использование такого инструмента, как SSIS, может быть более практичным?
Хорошо, это 90%, но вам нужно две другие вещи:
- справиться с ситуациями, когда идентификатор продукта уже существует - не пытайтесь вставить его второй раз, так как он потерпит неудачу;
- , где идентификатор продукта уже существует, обновите данные о цене.
Это должно обработать первый твик:
INSERT INTO Product (ProductId, ProductName, ProductUrl) SELECT t.TempProductId, t.TempProductName, t.TempProductUrl FROM tempDataTable t
WHERE NOT EXISTS (SELECT * FROM Product p WHERE p.ProductId = t.TempProductId);
... и UPDATE
цены, где данные уже существуют, или INSERT
их, если они не существуют, хорошо вы можете использовать MERGE
утверждение:
MERGE
ProductPricing AS [target]
USING (SELECT TempProductId, TempProductPrice, TempProductPricePerUnit, GETDATE() AS ProductPricingDate FROM tempDataTable)
AS [source] (
ProductId,
ProductPrice,
ProductPricePerUnit,
ProductPricingDate)
ON ([target].ProductId = [source].ProductId)
WHEN MATCHED THEN
UPDATE SET
ProductPrice = [source].ProductPrice,
ProductPricePerUnit = [source].ProductPricePerUnit,
ProductPricingDate = [source].ProductPricingDate
WHEN NOT MATCHED THEN
INSERT (
ProductId,
ProductPrice,
ProductPricePerUnit,
ProductPricingDate)
VALUES (
[source].ProductId,
[source].ProductPrice,
[source].ProductPricePerUnit,
[source].ProductPricingDate);
На самом деле, перечитывая ваш комментарий, я не думаю, что вам даже нужен MERGE
(но я все равно оставлю его там, как мне потребовалось немного усилий, чтобы написать это. Есть два сценария ios:
- , если для этого продукта уже есть запись - просто добавьте новую строку в таблицу ProductPricing, чтобы у вас был один продукт и две (или более) цены каждый с разной датой;
- , если это новый продукт - затем добавьте продукт и цену, чтобы у вас был один продукт и одна цена (пока не появится новая цена).
... и я не могу удержаться от добавления, это потому, что вы используете естественный ключ, то есть ключ из ваших данных, поэтому он не меняется при загрузке. Если вы использовали суррогатный ключ (например, IDENTITY
, полученный при вставке продукта), это не сработало бы, вам нужно go и найти суррогатный ключ, а затем использовать его, чтобы ваш внешний ключ ограничение работало правильно. Наверное, лучше не думать об этом слишком усердно?