Ответ 1
Нет, нет. Единственный способ избежать этой ошибки в запросе SELECT INTO
- это записать список столбцов после SELECT
вместо SELECT *
.
SQL Server не предлагает ключевое слово USING
в контексте JOIN
,
ни он не предоставляет NATURAL JOIN
.
Кроме того, явным образом (вручную) перечислены все столбцы (ссылка на другой дублированный вопрос), есть ли альтернатива получить таблицу, в которой столбцы, на которые я соединяюсь, которые имеют одинаковое имя в 2 соединенных таблицах, не дублируются?
В качестве промежуточного шага я попытался сохранить во временной таблице результат
SELECT INTO #MyTempTable * FROM tableA
INNER JOIN tableB
ON tableA.commonColumn = tableB.commonColumn;
Но я уже получаю сообщение об ошибке:
Имена столбцов в каждой таблице должны быть уникальными. Имя столбца "commonColumn" в таблице "#MyTempTable" указано более одного раза.
Нет, нет. Единственный способ избежать этой ошибки в запросе SELECT INTO
- это записать список столбцов после SELECT
вместо SELECT *
.
Единственная альтернатива - избежать SELECT
ing *
:
TableA
foo | bar
---------
TableB
foo | baz
---------
При выборе * из обеих таблиц в итоге вы получите 2 столбца с именем foo
, которые недопустимы в одной таблице.
Назовите выбранные столбцы с помощью уникальных имен, и это будет работать.
SELECT INTO #TableTemp t1.foo foo1, t1.bar, t2.foo foo2, t2.baz
FROM tableA t1
INNER JOIN tableB t2 ON t1.foo = t2.foo
Но пока вы на нем, не нужно вставлять общий столбец дважды (как t1.foo = t2.foo
). Выберите только один из них:
SELECT INTO #TableTemp t1.foo, t1.bar, t2.baz
FROM tableA t1
INNER JOIN tableB t2 ON t1.foo = t2.foo
РЕДАКТОР: Как сказал Филип Келли, эта проблема возникает только при попытке сохранить набор результатов в таблицу. Пока вы только выбираете данные, все работает отлично с повторяющимися именами столбцов.
Я бы не рекомендовал это, но, чтобы ответить на ваш вопрос, вы могли бы создать функцию sql clause builder, которая автоматически создает псевдонимы столбцов для ваших отдельных таблиц с префиксом tablename (или настраивать его, если хотите)
declare @tableName nvarchar(100);
set @tableName = 'TestTable';
select @tableName + '.' + c.name + ' AS ' + @tableName + '_' + c.name
from sys.tables t
inner join sys.columns c on c.object_id = t.object_id
where
t.name = @tableName
Вывод для моей маленькой таблицы с двумя столбцами
TestTable.TestColumn1 AS TestTable_TestColumn1
TestTable.TestColumn2 AS TestTable_TestColumn2
Гипотетическое использование
declare @sql nvarchar(1000) = '';
set @sql = myClauseBuilder('TestTable');
set @sql = @sql + ',' + myClauseBuilder('TestTable2');
set @sql = @sql + ' FROM TestTable INNER JOIN TestTable2....(etc.)
exec @sql
Это непросто. Но это возможно. Используя this, вы должны сначала создать два разделенных списка со всеми столбцами из двух таблиц, исключая общий столбец, к которому вы хотите присоединиться:
DECLARE @columnsA varchar(8000)
SELECT @columnsA = ISNULL(@columnsA + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tableA' AND COLUMN_NAME <> 'commonColumn'
ORDER BY ORDINAL_POSITION
DECLARE @columnsB varchar(8000)
SELECT @columnsB = ISNULL(@columnsB + ', ','') + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tableB' AND COLUMN_NAME <> 'commonColumn'
ORDER BY ORDINAL_POSITION
Затем вы будете использовать их для своего запроса, выбирая commonColumn только для одной из таблиц:
EXEC ('SELECT tableA.commonColumn, ' + @columnA + ', ' + @columnsB + ' FROM tableA INNER JOIN tableB ON tableA.commonColumn = tableB.commonColumn;')
Итак, есть хотя бы один способ сделать это.:) Это, по-видимому, также умеренно эффективно. Я не эксперт SQL, но я полагаю, что есть способ создать из этого функцию, возможно, одну функцию "выбрать все столбцы, но [...]", и одна функция, которая будет выполнять соединение как USING
, будет сделать.
Это становится немного проще, если в листинге мы добавим также содержащую таблицу. Таким образом, нам нужно извлечь только имена столбцов из одной таблицы.
DECLARE @columnsB varchar(8000)
SELECT @columnsB = ISNULL(@columnsB + ', ','') + QUOTENAME(table_name) + '.' + QUOTENAME(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tableB' AND COLUMN_NAME <> 'commonColumn'
ORDER BY ORDINAL_POSITION
И запрос изменен на:
EXEC ('SELECT tableA.* ', ' + @columnsB + ' FROM tableA INNER JOIN tableB ON tableA.commonColumn = tableB.commonColumn;')