2012-01-26 6 views
4

Используя Microsoft SQL 2000, я хотел бы объединить таблицы (A, B, C и D) вместе. Я знаю, что таблица А всегда существует. Тем не менее, я знаю только, что существует хотя бы одна из табличных форм (B, C, D).SQL-соединение нескольких таблиц

Есть ли способ сделать что-то подобное, чтобы выполнить то, что я пытаюсь сделать?

Select * form table a  
If table b exists left Join table b on a.id = b.id  
If table c exists left Join table c on a.id = c.id  
If table d exists left Join table d on a.id = d.id 

ответ

5

вы должны проверить мнения словаря данных для этого и использовать динамический SQL

declare @myquery varchar(1000) 

set @myquery = 'Select * from a ' 
if exists (select * from sysobjects where xtype='U' and name = 'b') 
begin 
    set @myquery = @myquery + 'inner join b on b.id = a.id ' 
end 
if exists (select * from sysobjects where xtype='U' and name = 'c') 
begin 
    set @myquery = @myquery + 'inner join c on c.id = a.id ' 
end 
if exists (select * from sysobjects where xtype='U' and name = 'd') 
begin 
    set @myquery = @myquery + 'inner join d on d.id = a.id ' 
end 

exec(@myquery) 

Я использовал sysobjects, однако вам рекомендуется использовать Information Schema Views вместо

и, в BIG DISCLAINER ON DYNAMIC SQL

Преимущества

  • Это обеспечивает гибкость и масштабируемость
  • Это может уменьшить количество строк кода, написанных

Недостатки

  • Это может стать очень комплекс d трудно читать. Подумайте о цитатах, встроенных в кавычки, и о других подобных вещах.
  • Это может отрицательно сказаться на стабильности кода. Некоторые ошибки динамического SQL не будут известны до времени выполнения. (Пример этого - где вы ссылаетесь на несуществующую таблицу)
  • Динамический SQL-код сложнее проверить, чем эквивалентный статический SQL. Также может быть невозможно проверить все возможные обстоятельства, с которыми столкнется ваш Dynamic SQL, тем самым внедряя присущий ему риск.
  • Будет сложнее провести эффективный анализ воздействия на Dynamic SQL в вашей базе кода.
  • SQL-инъекция и неправильное использование. Динамический SQL более подвержен неправильному использованию и неизменно менее безопасен, чем статический SQL.
  • Код запросов в Dynamic SQL не подпадает под план запроса и, поскольку такие оптимизации могут быть пропущены. Таким образом, он может быть медленнее, чем эквивалентный статический SQL.
  • Поскольку SQL-запрос неизвестен до выполнения, может быть сложнее настроить динамический код SQL (например, определить индексы, которые могут потребоваться для таблицы)
+2

+1 - Я бы добавил только эту ссылку: www.sommarskog.se/dynamic_sql.html – Lamak

+0

Вам следует избегать использования здесь, а вместо этого следует использовать Object_ID. – Pankaj

+0

@StackOverflow Пользователь: Не так. select * не имеет заметной разницы по имени поля: http://milambda.blogspot.com/2008/01/whats-wrong-with-count.html –

0

Вы не можете сделать условное соединение таким образом.

Вы можете просто сделать обычный LEFT JOIN. Если ни одна строка не соответствует критериям присоединиться, эти столбцы будут NULL:.

Select * 
from table a 
left Join table b on a.id = b.id 
left Join table c on a.id = c.id 
left Join table d on a.id = d.id 

Ь * столбцы могут быть NULL, или С * столбцы могут быть NULL, или D * столбцы могут быть NULL...

Если вам нужно выбрать первый ненулевой столбец, используйте COALESCE:

Select *, COALESCE(b.SOMECOLUMN, c.SOMECOLUMN, d.SOMECOLUMN) AS SOMECOLUMN 
from table a 
left Join table b on a.id = b.id 
left Join table c on a.id = c.id 
left Join table d on a.id = d.id 

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

+0

Вероятно, хочет *, COALESCE ... –

+1

@Cade Roux. - Я думаю, что вы неправильно, OP не знает, если * столы * B, C и D существуют. Использование динамического SQL было бы одним из вариантов решения этой проблемы. –

+1

Это работает? Даже если * таблица * не существует (а не любые строки * в * таблице)? – adelphus

-1

Возможно, вы имеете в виду, если результаты не являются самими таблицами.

SELECT * FROM TABLEA 
OUTER JOIN TABLEB ON TABLEA.id = TABLEB.id 
OUTER JOIN TABLEC ON TABLEA.id = TABLEC.id 
OUTER JOIN TABLED ON TABLEA.id = TABLED.id 

Вы просто получите нули для столбцов, где значение не совпало.

так что вы можете фильтровать с

WHERE TABLEB.id is not null 

и т.д.

+1

Нет, он говорит о самих таблицах –

1

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

declare @query varchar(1000) 

set @query = 'Select ColumnName from a ' 
if exists (select Object_ID from sys.tables where name = 'b') 
begin 
    set @query = @query + 'inner join b on b.id = a.id' 
end 
if exists (select Object_ID from sys.tables where name = 'c') 
begin 
    set @query = @query + 'inner join c on b.id = c.id' 
end 
if exists (select Object_ID from sys.tables where name = 'd') 
begin 
    set @query = @query + 'inner join d on d.id = a.id' 
end 

exec(@query) 
+0

Его sql 2000, 'sys.tables' появился только в SQL 2005 –

+0

Да :) sysobjects - очень общая терминология. Поэтому лучше использовать конкретные слова во время разработки, которые можно понять в определенном контексте как точка зрения разработчика, я надеюсь, что я прав :) – Pankaj

+0

что @JamesWiseman говорит, что вы используете 'sys.tables', которого не существует в SQL 2000, поэтому ваш запрос не будет работать – Lamak

Смежные вопросы