Как вставить строки одной таблицы в несколько таблиц с помощью хранимой процедуры SQL Server? - PullRequest
0 голосов
/ 27 апреля 2020

Я заинтересован во вставке моих строк tempDataTable в две таблицы.

Это дизайн таблицы моего tempdatatable:

TempDataTable

Две таблицы, которые я хочу создать с помощью хранимой процедуры из мой TempDataTable (один на картинке).

Дизайн для двух новых таблиц будет выглядеть примерно так:

  • Таблица первая (Product): ProductID (PK), ProductName, URL продукта
  • Table два (ProductPricing): ProductPricingID (PK), ProductId (FK), цена, priceperunit, дата

Это был полный день, когда я искал решение, и буду продолжать это делать, но я не могу найти точное решение. У меня нет опыта работы с SQL, но это то, что я должен сделать.

1 Ответ

1 голос
/ 27 апреля 2020

Хорошо, я точно не знаю, где вы боретесь, поэтому вот сценарий, который делает то, что вы просили. Ничего из этого не является слишком сложным для отслеживания, поэтому, возможно, проведите сканирование, а затем дайте мне знать, какие биты сбивают с толку?

Настройка структуры таблицы:

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 и найти суррогатный ключ, а затем использовать его, чтобы ваш внешний ключ ограничение работало правильно. Наверное, лучше не думать об этом слишком усердно?

...