2010-08-11 11 views
7

Estoy confundido con una consulta.Recuperar la última fila insertada con Uniqueidentifier que no es IDENTIDAD

necesito averiguar la última fila añadido en una tabla con una columna con tipo de datos Uniqueidentifier columna es: aspnet_Applications.ApplicationId Notas: Esta columna Uniqueidentifier NO y la columna de identidad es.

Necesito también tomar la última fila insertada y actualizarlo en una tabla diferente aspnet_Users.ApplicationId

me trató de usar SCOPE_IDENTITY en MS SQL 2008, pero no funciona porque SCOPE_IDENTITY está trabajando únicamente con columna de identidad.

Aquí mi código. ¿Algunas ideas?

CREATE DATABASE Test; 
GO 
USE Test; 
GO 

-- Create entities 
CREATE TABLE [dbo].[aspnet_Applications](
    [ApplicationName] [nvarchar](256) NOT NULL, 
    [LoweredApplicationName] [nvarchar](256) NOT NULL, 
    [ApplicationId] [uniqueidentifier] NOT NULL, 
    [Description] [nvarchar](256) NULL, 
PRIMARY KEY NONCLUSTERED 
(
    [ApplicationId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY], 
UNIQUE NONCLUSTERED 
(
    [LoweredApplicationName] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY], 
UNIQUE NONCLUSTERED 
(
    [ApplicationName] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[aspnet_Applications] ADD DEFAULT (newid()) FOR [ApplicationId] 
GO 


CREATE TABLE [dbo].[aspnet_Users](
    [ApplicationId] [uniqueidentifier] NOT NULL, 
    [UserId] [uniqueidentifier] NOT NULL, 
    [UserName] [nvarchar](256) NOT NULL, 
    [LoweredUserName] [nvarchar](256) NOT NULL, 
    [MobileAlias] [nvarchar](16) NULL, 
    [IsAnonymous] [bit] NOT NULL, 
    [LastActivityDate] [datetime] NOT NULL, 
PRIMARY KEY NONCLUSTERED 
(
    [UserId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[aspnet_Users] WITH CHECK ADD FOREIGN KEY([ApplicationId]) 
REFERENCES [dbo].[aspnet_Applications] ([ApplicationId]) 
GO 

ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (newid()) FOR [UserId] 
GO 

ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT (NULL) FOR [MobileAlias] 
GO 

ALTER TABLE [dbo].[aspnet_Users] ADD DEFAULT ((0)) FOR [IsAnonymous] 
GO 

-- Add data 
DECLARE @MyIdentity binary(16); 
INSERT INTO dbo.aspnet_Applications 
(
    ApplicationName, 
    LoweredApplicationName, 
    Description 
) 
VALUES 
(
    'x', 
    'x', 
    'Dummy text' 
); 
SET @MyIdentity = SCOPE_IDENTITY(); -- DOES NOT WORK 
PRINT @MyIdentity; -- DOES NOT WORK 

INSERT INTO dbo.aspnet_Users 
(
    ApplicationId, 
    UserName, 
    LoweredUserName, 
    MobileAlias, 
    IsAnonymous, 
    LastActivityDate 
) 
VALUES 
( 
    @MyIdentity, 
    'Administrator', 
    'administrator', 
    '', 
    0, 
    sysutcdatetime() 
); 
+1

+1 Para DDL útil por cierto. Aunque –

+0

(OMI) que no es necesario identificadores únicos (columna de identidad haría el trabajo y le dará un mejor rendimiento), incluso con GUID puede haber agrupado claves primarias si utiliza SET @MyIdentity = NEWSEQUENTIALID(). También puede usar NewSequentialID() como valor predeterminado para las columnas de ID y obtener valores insertados utilizando la instrucción OUTPUT tal como lo propuso Martin. – Niikola

Respuesta

13

Es un poco más de trabajo, pero para sus inserciones, a pesar de que ya tiene un valor por defecto en la ApplicationID, que podría hacer esto:

DECLARE @MyIdentity uniqueidentifier; 
SET @MyIdentity = NewID(); 
INSERT INTO dbo.aspnet_Applications 
(
    ApplicationName, 
    LoweredApplicationName, 
    ApplicationId, 
    Description 
) 
VALUES 
(
    'x', 
    'x', 
    @MyIdentity, 
    'Dummy text' 
); 

SELECT @MyIdentity 

En esencia, se establece el GUID de antemano, para que ya sepas lo que insertarás.

+0

¡gran solución! – GibboK

4

Usted podría utilizar la cláusula OUTPUT para obtener el valor insertado (s) atrás pero LBT's answer es probablemente más sencillo y eficiente.

DECLARE @ids table(id uniqueidentifier) 

INSERT INTO dbo.aspnet_Applications 
(
    ApplicationName, 
    LoweredApplicationName, 
    Description 
) 
OUTPUT INSERTED.ApplicationId into @ids 
VALUES 
(
    'x', 
    'x', 
    'Dummy text' 
) 

Por cierto, si no fuera por la clave externa se puede usar para este composable DML de la siguiente manera.

INSERT 
INTO dbo.aspnet_Users 
     (
       ApplicationId , 
       UserName  , 
       LoweredUserName, 
       MobileAlias , 
       IsAnonymous , 
       LastActivityDate 
     ) 
SELECT ApplicationId , 
     'Administrator', 
     'administrator', 
     ''    , 
     0    , 
     sysutcdatetime() 
FROM (INSERT 
     INTO dbo.aspnet_Applications 
       (
         ApplicationName  , 
         LoweredApplicationName, 
         Description 
       ) 
       OUTPUT INSERTED.ApplicationId VALUES 
       (
         'x', 
         'x', 
         'Dummy text' 
       ) 
     ) AS I 
Cuestiones relacionadas