2013-06-10 4 views
1

Я беру запрос из базы данных, используя две таблицы, и получаю ошибку, описанную в заголовке моего вопроса. В некоторых случаях поле, к которому я должен выполнить запрос, находится в таблице A, но другие находятся в таблице B. Я динамически создаю столбцы для поиска (которые могут быть либо в таблице A, либо в таблице B), и мое предложение WHERE в моем коде вызывая ошибку.Как исправить ошибку «неоднозначное имя столбца с использованием внутреннего соединения»

Есть динамический способ исправить это, например, если столбец в таблице B, то поиск с помощью таблицы B, или же INNER JOIN должен это исправить (который в настоящее время не является)

Таблица А поля: ID

Таблица B поля: идентификатор


SQL код

SELECT * 
FROM A INNER JOIN B ON A.id = B.id 
WHERE 
<cfloop from="1" to="#listLen(selectList1)#" index="i"> 

    #ListGetAt(selectList1, i)# LIKE UPPER(<cfqueryparam cfsqltype="cf_sql_varchar" value="%#ListGetAt(selectList2,i)#%" />) <!--- 
                search column name = query parameter 

                using the same index in both lists 
                (selectList1) (selectList2) ---> 
    <cfif i neq listLen(selectList1)>AND</cfif> <!---append an "AND" if we are on any but 
               the very last element of the list (in that 
               case we don't need an "AND"---> 
</cfloop> 

Question posed here too

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

+1

Вы динамически добавлять операторы SQL? Если да, то все столбцы добавлены в псевдонимы таблицы, IE. A. column, B.column? – BClaydon

ответ

6
Employee 
------------------ 
Emp_ID Emp_Name Emp_DOB Emp_Hire_Date Emp_Supervisor_ID 


Sales_Data 
------------------ 
Check_ID Tender_Amt Closed_DateTime Emp_ID 

Каждый столбец, на который вы ссылаетесь, должен выполняться псевдонимом таблицы (но вы уже знали это.) Например;

SELECT E.Emp_ID, B.Check_ID, B.Closed_DateTime 
FROM Employee E 
    INNER JOIN Sales_Data SD ON E.Emp_ID = SD.Emp_ID 

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

SELECT * 
FROM Employee E 
    INNER JOIN Sales_Data SD ON E.Emp_ID = SD.Emp_ID 

компилятор видит это как:

**Emp_ID**, Emp_Name, Emp_DOB, Emp_Hire_Date, Emp_Supervisor_ID, 
Check_ID, Tender_Amt, Closed_DateTime, **Emp_ID** 

Поскольку он пытается получить все столбцы из обеих таблиц emp_id дублируется, но SQL не знает из которого вызывается Emp_ID, поэтому вы получаете «неоднозначную ошибку имени столбца, используя внутреннее соединение».

Таким образом, вы не можете использовать (*), потому что любые имена столбцов, которые существуют в обеих таблицах, будут неоднозначными. Скорее всего, вам не нужны все столбцы.

Кроме того, если вы добавляете какие-либо столбцы в строку SELECT через ваш cfloop, они также должны выполнять псевдоним таблицы.

-Edit: Я очистил примеры и изменил «SELECT * вытащил все столбцы из первой таблицы» на «SELECT * вытащил все столбцы из обеих таблиц». Шон указал, что я ошибался.

+0

* Фактически ссылки на все столбцы в запросе не так ли? Хотя вы можете, конечно, «A. *» или «B. *». Как правило, предпочтительнее назвать столбцы, необходимые для ясности. –

+0

* относится ко всем столбцам в запросе. Вышеуказанный запрос создает два столбца ID. И любые другие столбцы с одинаковым именем в обеих таблицах будут дублированы. Вот почему есть ошибка. Если вы попытаетесь отсортировать по любому из этих столбцов, не указав псевдоним таблицы, SQL не сможет указать, в каком столбце вы ссылаетесь. Табличные псевдонимы и ссылающиеся на них в предложении WHERE псевдонимом должны устранить эту проблему. – Shawn

+0

И я согласен с Саймоном. SELECT * обычно не подходит. Это больше набирает текст, но перечисляет столбцы, которые вам действительно нужно возвращать в результатах. И только те столбцы. Если вам нужно всего два или три столбца из каждой таблицы, вам не нужно выбирать каждый столбец в обеих таблицах. Это сделает ваш запрос более эффективным и удобочитаемым. – Shawn

2

Вы должны написать свое предложение where таким образом, чтобы вы могли указать A.field_from_A или B.field_from_B. Вы всегда можете пройти A.field_from_A.

Хотя, на самом деле не хочу сказать

SELECT * FROM A INNER JOIN B ON A.id=B.id where B.id = '1'.

Вы хотели бы сказать

SELECT * FROM B INNER JOIN A ON B.id=A.id where B.id = '1'

Вы можете получить некоторые действительно медленные запросы, если вы пытаетесь использовать присоединяемой таблицы в ИНЕКЕ. Бывают случаи, когда это неизбежно, но лучше всего всегда иметь предложение where where только из основной таблицы.

+0

Получил ссылку на это последнее заявление, которое вы делаете? Это звучит интересно, и я хотел бы прочитать об этом. Приветствия. –

+0

Я не видел никаких ссылок в этом, но анонимно видел некоторые незначительные проблемы с производительностью, когда я ставил все предельные критерии в пределах WHERE по сравнению с тем, чтобы помещать ограничения присоединения для конкретных JOIN. Разумеется, это может быть MySQL, характерный в этих примерах, когда дело доходит до оптимизации. К сожалению, у меня нет источников для подтверждения того или другого. –

+0

Мои наблюдения состоят в том, что ссылка на объединенную таблицу в предложении where не влияет на производительность. Однако я не использую MySQL. –

1

Когда вы собираете переменную select1, добавьте имена таблеток или псевдонимы. Другими словами, вместо того, напоминающего это:

select1 = "fred,barney,wilma,pebbles"; 

Сделать его похожим на это:

select1 = "a.fred,a.barney,b.wilma,b.pebbles"; 
Смежные вопросы