SQL: вставить все записи из одной таблицы в другую таблицу без конкретных столбцов

Я хочу вставить всю запись из резервной таблицы foo_bk в таблицу foo без конкретных столбцов.

если я попробую этот запрос

INSERT INTO foo 
SELECT *
FROM foo_bk

я получу ошибку "Вставить ошибку: имя столбца или количество предоставленных значений не соответствует определению таблицы."

Можно ли выполнять массовую вставку из одной таблицы в другую без указания имени столбца? У меня есть Google, но я не могу найти ответ. все ответы требуют конкретных столбцов.

Ответ 1

Вы никогда не должны этого делать. Select * не следует использовать в качестве основы для вставки, так как столбцы могут перемещаться и разбивать вашу вставку (или, что еще хуже, не разбивать вашу вставку, а испортить ваши данные. Предположим, кто-то добавляет столбец в таблицу в выбранном, но не другой стол, ваш код сломается. Или предположите, что кто-то по причинам, которые превосходят понимание, но часто случается, решает сделать снимок и воссоздать на столе и переместить столбцы в другой порядок. Теперь ваше последнее имя - это место first_name изначально и select * помещает его в неправильный столбец в другой таблице. Крайне плохая практика не позволяет указать столбцы и конкретное сопоставление одного столбца столбцу, который вы хотите в интересующей вас таблице.

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

Ответ 2

За это другое сообщение: Вставить все значения a..., вы можете сделать следующее:

INSERT INTO new_table (Foo, Bar, Fizz, Buzz)
SELECT Foo, Bar, Fizz, Buzz
FROM initial_table

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

Ответ 3

Используйте этот

SELECT *
INTO new_table_name
FROM current_table_name

Ответ 4

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

Для массового переноса проверьте документацию по используемой вами реализации SQL. Часто доступны инструменты для массового переноса данных из одной таблицы в другую. Например, для SqlServer 2005 можно использовать мастер импорта и экспорта SQL Server. Щелкните правой кнопкой мыши базу данных, в которую вы пытаетесь переместить данные, и нажмите "Экспорт", чтобы получить доступ к ней.

Ответ 5

SQL 2008 позволяет отказаться от указания имен столбцов в SELECT, если вы используете SELECT INTO, а не INSERT INTO/SELECT:

SELECT *
INTO Foo
FROM Bar
WHERE x=y

Предложение INTO существует в SQL Server 2000-2005, но по-прежнему требует указания имен столбцов. 2008, похоже, добавляет возможность использовать SELECT *.

См. статьи MSDN на INTO (SQL2005), (SQL2008) для деталей.

Предложение INTO работает только в том случае, если таблица назначения еще не существует. Если вы хотите добавить записи в существующую таблицу, это не поможет.

Ответ 6

Как вы, вероятно, поняли из предыдущих ответов, вы не можете делать то, что вам нужно. Я думаю, вы можете понять проблему, с которой сталкивается SQL Server, не зная, как сопоставить дополнительные/отсутствующие столбцы.

Тем не менее, поскольку вы упоминаете, что цель того, что вы пытаетесь сделать здесь, - это резервное копирование, возможно, мы можем работать с SQL Server и обходить проблему. Не зная вашего точного сценария, невозможно получить правильный ответ здесь, но я предполагаю следующее:

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

Я хочу предложить вам два варианта:

Эффективная практика (IMO) для этого может заключаться в обнаружении изменений схемы с использованием триггеров DDL и их использовании для изменения таблицы резервного копирования. Это позволит вам использовать подход "select * from...", потому что список столбцов будет согласован между двумя таблицами.

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

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

create table foo (id int, name varchar(50))
create table foo_bk (id int, name varchar(50), tagid int)
go

create view vw_foo as select id,name from foo 
go

create view vw_foo_bk as select id,name from foo_bk
go

insert into vw_foo
    select * from vw_foo_bk 
go

drop view vw_foo
drop view vw_foo_bk
drop table foo
drop table foo_bk
go

Надеюсь, это поможет:)

Ответ 7

Все ответы, приведенные выше, по тем или иным причинам у меня не работали на SQL Server 2012. Моя ситуация была, когда я случайно удалил все строки вместо одной. После того, как наш администратор восстановил таблицу в dbo.foo_bak, я использовал приведенное ниже для восстановления. ПРИМЕЧАНИЕ. Это работает только в том случае, если таблица резервного копирования (представленная dbo.foo_bak) и таблица, в которую вы пишете (dbo.foo), имеют одинаковые имена столбцов.

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

USE [database_name];
GO
SET IDENTITY_INSERT dbo.foo ON;
GO
INSERT INTO [dbo].[foo]
           ([rown0]
           ,[row1]
           ,[row2]
           ,[row3]
           ,...
           ,[rown])
     SELECT * FROM [dbo].[foo_bak];
GO
SET IDENTITY_INSERT dbo.foo OFF;
GO

Эта версия моего ответа полезна, если у вас есть первичные и внешние ключи.