OUPUT для вставки из табличной переменной дает: «Не удалось связать многослойный идентификатор« k.CustomerName ». - PullRequest
2 голосов
/ 20 декабря 2011

Я видел здесь много людей, переполненных стеком с этим сообщением об ошибке, и все получили его в другой ситуации.Я не мог найти свою ситуацию среди уже существующих вопросов.Поэтому я надеюсь, что кто-то может помочь мне с этим.Я использую SQL Server 9 с SQL Management Studio 10.

--import the customers.
CREATE TABLE #AllCustomers(CustomerName NVARCHAR(100), CustomerNr NVARCHAR(16));
BULK INSERT #AllCustomers
FROM 'C:\allcustomers.txt' 
WITH 
( 
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
);

DECLARE @DefinitionId int;

--get the id of the definition for which I have to set values.
SELECT @DefinitionId = pkDefinitionId
FROM dbo.Definitions
WHERE Name = 'DEFINITION-OF-MY-ITEM';

DECLARE @TempA TABLE (CustomerName NVARCHAR(255), CustomerNr NVARCHAR(16));

--reduce the set of all customers to only the customer for whom I have to insert.
WITH MyView AS 
    (SELECT kciv.CustomerNr
     FROM dbo.CustomerItems kciv
     INNER JOIN dbo.DefinitionToItem civ ON civ.pkDefinitionToItemId = kciv.pkCustomerItemId
     WHERE civ.fkDefinitionId = @DefinitionId)
INSERT INTO @TempA 
SELECT k.CustomerName , k.CustomerNr 
FROM #AllCustomers k
WHERE k.CustomerNr NOT IN (SELECT CustomerNr FROM MyView);

--used to store the generated primairy keys I need for creating relations.
DECLARE @ItemIds TABLE (CustomerName NVARCHAR(255), CustomerNr NVARCHAR(16), pkItemId int);
DECLARE @DefinitionToItemIds TABLE (CustomerName NVARCHAR(255), CustomerNr NVARCHAR(16), pkDefinitionToItemId int);

--insert the default values.
INSERT INTO dbo.Items
OUTPUT k.CustomerName, k.CustomerNr, inserted.pkItemId 
  INTO @ItemIds (CustomerName, CustomerNr, pkGenericValueId)
SELECT 2, 1, null, null, 1, null
FROM @TempA k;

--couple the values to the definition.
INSERT INTO dbo.DefinitionToItem
OUTPUT gvd.CustomerName, gvd.CustomerNr, inserted.pkDefinitionToItemId 
  INTO @DefinitionToItemIds
SELECT 1, 0, @DefinitionId, gvd.pkItemId
FROM @ItemIds gvd;

--couple the 'coupling' to the customers.
INSERT INTO dbo.CustomerItems
SELECT civd.pkDefinitionToItemId, civd.CustomerName, civd.CustomerNr
FROM @DefinitionToItemIds civd;

Я получаю четыре ошибки при выполнении запроса, все в двух выходных строках в конце примера кода.

Сообщение 4104, уровень 16, состояние 1, строка 64 Не удалось связать идентификатор из нескольких частей «k.CustomerName».
Сообщение 4104, уровень 16, состояние 1, строка 64 Идентификатор из нескольких частей «k.CustomerNr "не может быть привязан.
Сообщение 4104, уровень 16, состояние 1, строка 69 Не удалось связать идентификатор из нескольких частей" gvd.CustomerName ".
Сообщение 4104, уровень 16, состояние 1, строка 69Не удалось связать многокомпонентный идентификатор "gvd.CustomerNr".

Я проверил опечатки, но не смог их найти (я мог бы ввести некоторые здесь, хотя изменил некоторые имена, чтобы удалить контекст).Я не могу понять, почему это идет не так.Я посмотрел на MSDN , но не могу найти ничего плохого.

Дополнительная информация:

Схема базы данных выглядит следующим образом:

  • Таблица Items содержит «значения» (pkItemId, куча других столбцов)
  • Таблица Definition содержит «определения» (pkDefinitionId, Name, куча других столбцов)
  • Таблица DefinitionToItem сопоставляет значения определений (pkDefinitionToItemId, fkDefinitionId, fkItemId)
  • Ссылки таблицы CustomerItemsклиента к DefinitionToItemId (pkDefinitionToItemId, CustomerName, CustomerNr).

Что мне нужно сделать, это вставить значения по умолчанию (то есть "2, 1, ноль, ноль, 1, ноль", связанный с определением'DEFINITION-OF-MY-ITEM') в базе данных товаров для данного набора клиентов.Некоторые могут уже иметь значение для этого определения, и тогда я должен пропустить их (отсюда и @TempA).Поэтому я вставляю значение в Items, затем вставляю связь между определением и элементами в DefinitionToItem и, наконец, связываю клиента с DefinitionToItem, вставляя в таблицу DefinitionToItem.

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

Ответы [ 3 ]

2 голосов
/ 20 декабря 2011

Я думаю, что ваш подход усложняет сценарий.

Во-первых, предложение OUTPUT не будет работать так, как вам нужно, чтобы работать здесь, потому что вы можете использовать только вставленные столбцы, и вы хотите использовать столбцы из исходной таблицы, но те, которые не вставляются. (CustomerName в качестве примера).

Я предлагаю вам два способа:

  1. Первый подход . Измените ваш запрос. Используйте OUTPUT, но выведите поле id. Затем, после первой вставки в ITEMS, объедините новую таблицу с исходной таблицей. ТЕПЕРЬ вы будете иметь доступ ко всем полям и сможете определить, какие записи следует вставить.

  2. Второй подход . Оставьте свои временные таблицы. Используйте простой оператор вставки с предложением WHERE _ NOT IN. Это устраняет сложность и все еще достигает цели не вставлять дубликаты, только на более близком уровне.

1 голос
/ 20 декабря 2011

Ваша таблица #AllCustomers не содержит поле CustomerName в этом запросе

SELECT k.CustomerName , k.CustomerNr 
FROM #AllCustomers k
1 голос
/ 20 декабря 2011

Использование:

INSERT INTO dbo.Items
OUTPUT INSERTED.CustomerName, INSERTED.CustomerNr, INSERTED.pkItemId 
  INTO @ItemIds (CustomerName, CustomerNr, pkGenericValueId)
SELECT 2, 1, null, null, 1, null
  FROM @TempA k;

INSERT INTO dbo.DefinitionToItem
OUTPUT INSERTED.CustomerName, INSERTED.CustomerNr, INSERTED.pkDefinitionToItemId 
  INTO @DefinitionToItemIds
SELECT 1, 0, @DefinitionId, gvd.pkItemId
  FROM @ItemIds gvd;

Возможно, вам придется изменить имена столбцов, поскольку они должны исходить из вставляемой таблицы, а не из столбца, из которого они получены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...