Insertar filas en una tabla con una sola columna de IDENTIDAD

83

Tengo un administrador de tabla con una sola columna, adminId, que es la clave principal. Debido a las reglas comerciales, tiene que ser así.

Me gustaría entender de una vez por todas cómo puedo escribir procedimientos almacenados que inserten valores en tablas como esta. Estoy usando SQL Server y T-SQL e intenté usar SCOPE_IDENTITY () pero eso no funciona ya que la tabla tiene INSERT_IDENTITY en falso o apagado.

Realmente me gustaría no insertar un valor ficticio solo para poder insertar una nueva fila. ¡Gracias!

Phil
fuente
1
Para aclarar: su pregunta es "¿cómo insertar filas en una tabla de SQL Server con una sola columna de IDENTIDAD"?
gbn
Sí, tiene razón, gracias por aclarar
Phil
2
Para las personas que aterrizan aquí, esto se ha preguntado antes y la respuesta correcta está aquí: stackoverflow.com/questions/850327/…
BJury

Respuestas:

140

Si tiene una columna que es una IDENTIDAD, simplemente haga esto

INSERT MyTable DEFAULT VALUES;  --allows no column list. The default will be the IDENTITY
SELECT SCOPE_IDENTITY();

Si no tiene identidad, ¿puede configurarla? Esta es la mejor manera ... y usa el SQL anterior.

Si no es así, desea insertar una nueva fila.

INSERT MyTable (admidid)
OUTPUT INSERTED.admidid --returns result to caller
SELECT ISNULL(MAX(admidid), 0) + 1 FROM MyTable

Notas:

  • Bajo cargas elevadas, la solución MAX puede fallar con duplicados
  • SCOPE_IDENTITY es posterior al hecho, no antes
  • SCOPE_IDENTITY solo funciona con una columna IDENTITY. Lo mismo ocurre con cualquier idiotez usando IDENT_CURRENT
  • La cláusula de salida reemplaza SCOPE_IDENTITY para la solución MAX
gbn
fuente
1

Debe agregar IDENTITY_INSERT a su declaración de selección:

SET IDENTITY_INSERT MyTable ON

INSERT INTO MyTable
(AdminCol)

SELECT AdminColValue

 FROM Tableb

Cuando haya terminado, asegúrese de recordar

SET IDENTITY_INSERT MyTable OFF

Aquí hay una buena descripción de cómo funciona desde BOL: http://msdn.microsoft.com/en-us/library/aa259221(SQL.80).aspx

DataWriter
fuente
¿Se supone que debo hacerlo así: SET IDENTITY_INSERT Administrador ON INSERT INTO Administrador (SCOPE_IDENTITY ()) SET IDENTITY_INSERT Administrador OFF?
Phil
Si. Eso es todo lo que necesitas hacer. SET ON, escribe tu código, SET OFF al final.
DataWriter
No creo que esta sea la respuesta correcta. Si es una columna de identidad, no debería agregarle valores. La respuesta aceptada es la respuesta correcta.
Mmm
0

@Phil: ¿No quiere decir que su tabla tiene dos (2) columnas, la columna PK de aumento automático y una columna AdminName? Si solo tiene una columna donde va el AdminName, el AdminName es el PK y, por supuesto, no puede aumentar automáticamente una cadena. ¿Esperan las reglas de negocio que establezca un nombre de usuario de Windows totalmente calificado como clave principal? Eso sería viable y tendría sentido, porque entonces no necesitaría un índice único alternativo en la columna AdminName.

Pero si su tabla tiene dos columnas, no una:

En SQLServer, el autoincremento es parte de la definición de tabla / columna. Usted define la columna como un número entero y luego también la convierte en una columna de identidad, especificando el incremento, generalmente 1, pero podría ser 2 o 5 o 10 o lo que sea. Para insertar una fila, simplemente inserte los valores de las otras columnas y no haga nada con la columna PK:

insert into T
(foo)   -- column(s) list
values('bar') -- values list

Su proceso almacenado que realiza la inserción puede hacer que SCOPE_IDENTITY sea un valor RETURN o SCOPE_IDENTITY se puede devolver al cliente como un parámetro OUT.

PS SCOPE_IDENTITY () devuelve el valor de identidad autoincrementado generado más recientemente en el ámbito actual; no genera el siguiente valor de identidad.

EDITAR:

Presumiblemente, su tabla Administradores contiene un conjunto de administradores. Pero si no tiene ninguna columna que no sea la columna de clave primaria entera, no hay forma de identificar a los administradores; lo único que puede hacer es distinguirlos entre sí. Eso no te lleva muy lejos. Pero si su tabla de administrador tenía alguna de las siguientes estructuras:

ID   INTEGER PRIMARY KEY AUTOINCREMENT
windowsusername   varchar(50)  (unique index)

O

windowsusername varchar(50) primary key

podría hacer referencia a la tabla del administrador desde otras tablas, y las claves externas serían SIGNIFICATIVAS. Y eso es precisamente lo que le falta a una tabla que consta de una sola columna de números enteros: significado.

Al tener dos columnas, puede hacer que un procedimiento almacenado haga esto:

insert into Administrators
(windowsusername)
values('mydomain\someusername');
return SCOPE_IDENTITY();

y su programa-cliente recuperaría como valor de retorno el ID autoincrementado que se había generado automáticamente y asignado a la fila recién insertada. Este enfoque es la práctica habitual y me atrevería a decir que se considera una "mejor práctica".

PD: Mencionas que no sabías cómo "insertar un valor" si "no tenías nada que insertar". Hay una contradicción ahí. Si no tiene nada que insertar, ¿por qué hacerlo? ¿Por qué crearía, digamos, un nuevo registro de CLIENTE si no sabe absolutamente nada sobre el cliente? ¿No es su nombre, su ciudad, su número de teléfono, nada?

Tim
fuente
2
Mi tabla tiene UNA columna, adminId, que es un valor int incremental
Phil
Ese es el diseño más extraño que he visto en mi vida, y he estado en el negocio durante más de 20 años y he visto algunas cosas extrañas en mi época. Entonces, su pregunta es, ¿cómo se inserta en una tabla que contiene solo una columna de clave principal definida como una columna de identidad de autoincremento, cuando la tabla contiene esa columna PK y solo esa columna PK, no otras columnas?
Tim
Entonces, ¿para qué es el voto negativo? ¿Un error fáctico en alguna parte o por expresar una opinión sobre la falta de mérito del diseño?
Tim
1
Solo para aclarar el razonamiento detrás del diseño DB. Tenemos usuarios en una mesa. Si existe una relación entre usuarios y administradores; se tratan como administradores. No hay nada más que mantener en la tabla de administración que la identificación única real. Los datos "reales" están en la tabla de usuarios y la relación de has (con marcas de tiempo y quién concedió, etc.).
Phil
1
@Phil: Entonces estás usando una tabla y una relación de clave externa para expresar lo que podría hacer una simple columna booleana / bit. Es posible que no pueda agregar una columna de este tipo a su tabla y tenga que encontrar una solución alternativa. But an autoincrementing integer whose autoincrementation must be disabled is a poor solution.Todo lo que necesita es una tabla paralela con una relación de uno a uno con la tabla de usuarios y en esa tabla crea una columna de bits. Cuando esa columna es verdadera, significa que el usuario tiene administrador. Limpiar. Estándar. Diseño.
Tim