sql - modificar - Insertar en... Seleccione*, ¿cómo ignorar la identidad?
sql convertir un campo en identity (9)
Tengo una tabla temporal con la estructura exacta de una mesa de concreto T. Fue creada así: selecciona la parte superior 0 * en #tmp de T
Después de procesar y completar el contenido en #tmp, quiero copiar el contenido de nuevo a T como este: insertar en T seleccionar * de #tmp
Esto está bien siempre que T no tenga una columna de identidad, pero en mi caso sí. ¿Hay alguna forma en que pueda ignorar la columna de autoincremento de #tmp cuando copie a T? Mi motivación es evitar tener que deletrear cada nombre de columna en la lista Insertar en.
EDITAR: Alternar identity_insert no funcionaría porque los pkeys en #tmp pueden colisionar con los de T si las filas se insertaron en T fuera de mi script, eso es si #tmp ha autoincrementado la pkey para sincronizar con T en primer lugar.
- me da la oportunidad de obtener una vista previa de los datos antes de hacer la inserción
- Tengo uniones entre tablas temporales como parte de mi cálculo; Las tablas temporales me permiten enfocarme en los datos exactos del set con los que estoy trabajando. Creo que eso fue todo. ¿Alguna sugerencia / comentario?
Para la parte 1, tal como lo mencionó Kolten en uno de los comentarios, encapsular sus declaraciones en una transacción y agregar un parámetro para alternar entre la visualización y la confirmación satisfará sus necesidades. Para la Parte 2, necesitaría ver qué "cálculos" está intentando hacer. Limitar sus datos a una tabla temporal puede complicar la situación.
¿Podría funcionar una "actualización donde T.ID = # tmp.ID"?
No con SELECT *
: si seleccionó cada columna menos la identidad, estará bien. La única forma en que puedo ver es que puedes hacer esto construyendo dinámicamente la INSERT
.
SET IDENTITY_INSERT ON
Comando INSERTAR
SET IDENTITY_INSERT OFF
Simplemente haga una lista de las columnas que desea volver a insertar, nunca debe usar seleccionar * de todos modos. Si no desea escribirlos, simplemente arrástrelos desde el navegador de objetos (si expande la tabla y arrastra la palabra, columnas, obtendrá todos ellos, simplemente elimine la columna de identificación)
INSERT INTO #Table SELECT MAX (Id) + ROW_NUMBER () OVER (ORDER BY Id)
set identity_insert on
Utilizar esta.
Como la identidad se generará durante la inserción de todos modos, ¿podría simplemente eliminar esta columna de #tmp antes de volver a insertar los datos en T?
alter table #tmp drop column id
UPD: Aquí hay un ejemplo que he probado en SQL Server 2008:
create table T(ID int identity(1,1) not null, Value nvarchar(50))
insert into T (Value) values (N''Hello T!'')
select top 0 * into #tmp from T
alter table #tmp drop column ID
insert into #tmp (Value) values (N''Hello #tmp'')
insert into T select * from #tmp
drop table #tmp
select * from T
drop table T
select * into without_id from with_id
union all
select * from with_id where 1 = 0
Razón:
Cuando se selecciona una columna de identidad existente en una nueva tabla, la nueva columna hereda la propiedad IDENTITY, a menos que una de las siguientes condiciones sea verdadera:
- La instrucción SELECT contiene una combinación, una cláusula GROUP BY o una función agregada.
- Se unen múltiples instrucciones SELECT utilizando UNION.
- La columna de identidad aparece en la lista más de una vez en la lista de selección.
- La columna de identidad es parte de una expresión.
- La columna de identidad proviene de una fuente de datos remota.
Si alguna de estas condiciones es verdadera, la columna se crea NOT NULL en lugar de heredar la propiedad IDENTITY. Si se requiere una columna de identidad en la nueva tabla, pero dicha columna no está disponible, o si desea un valor inicial o de incremento diferente de la columna de identidad de origen, defina la columna en la lista de selección usando la función IDENTIDAD. Consulte "Crear una columna de identidad usando la función IDENTIDAD" en la sección de Ejemplos a continuación.
Todo el mérito recae en Eric Humphrey y bernd_k