Структура запроса DB2, использующая пользовательскую функцию в виде таблицы - PullRequest
0 голосов
/ 01 сентября 2011

Я немного новичок в DB2, и у меня возникают проблемы при разработке запроса.Я создал пользовательскую функцию, которая возвращает таблицу данных, к которой я хочу присоединиться и выбрать в более крупном операторе выбора.Я работаю над чувствительной БД, поэтому приведенный ниже запрос - это не то, что я в буквальном смысле выполняю, но он почти такой же (без других 10 объединений, которые я должен выполнить).

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  INNER JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35

Это прекрасно работает, если я запускаю этот запрос без предложения where (или другого предложения where, которое не проверяет идентификатор).Когда я включаю предложение where, я получаю следующую ошибку:

Ошибка при подготовке 58004 (-901) [IBM] [Драйвер CLI] [DB2 / LINUXX8664] SQL0901N Оператор SQL не выполнен из-занесерьезная системная ошибка.Последующие операторы SQL могут быть обработаны.(Причина «Неверный план; найден неразрешенный QNC».) SQLSTATE = 58004

Я обнаружил проблему, поскольку я использую один из критериев соединения для параметров (B.customerId).Я подтвердил этот факт, заменив B.customerId действительным customerId, и запрос отлично работает.Проблема в том, что я не знаю customerId при вызове этого запроса.Я знаю только orderId (в этом примере).

Есть мысли о том, как реструктурировать это, чтобы я мог сделать только один звонок, чтобы получить всю информацию?Я знаю, что план - это проблема, потому что до вызова функции не решен customerId.

Ответы [ 2 ]

0 голосов
/ 06 сентября 2011

я обнаружил, что лучшее решение (учитывая текущую структуру запроса) состоит в том, чтобы использовать левое соединение вместо внутреннего соединения, чтобы заставить левую часть соединения произойти, что приведет к тому, что customerId получит значение к тому времени, когда оно получит на вызов функции.

select 
  A.customerId,
  A.firstname,
  A.lastname,
  B.orderId,
  B.orderDate,
  F.currentLocationDate,
  F.currentLocation
from 
  customer A
  INNER JOIN order B
    on A.customerId = B.customerId
  LEFT JOIN table(getShippingHistory(B.customerId)) as F
    on B.orderId = F.orderId
where B.orderId = 35
0 голосов
/ 02 сентября 2011

Так что, если я правильно понимаю, функция getShippingHistory (customerId) возвращает таблицу.

И если вы вызываете ее с одним идентификатором клиента, эта таблица присоединяется к вашему запросу выше, без проблем.

Но так, как вы написали запрос выше, вы просите db2 вызывать функцию для каждой строки, возвращаемой вашим запросом (т. Е. Для каждого b.customerId, который соответствует вашему соединению и условиям).

Поэтому я не уверен, какое поведение вы ожидаете, потому что вы запрашиваете таблицу назад для каждой строки в вашем запросе, и db2 (ни я) может выяснить, как должен выглядеть результат.

Итак, с точки зрения реструктуризации вашего запроса, подумайте, как можно изменить логику getShippingHistory, когда задействованы несколько идентификаторов клиентов.

...