SQL Server: как обновить таблицу на основе подзапроса в предложении where? - PullRequest
3 голосов
/ 31 марта 2011

У меня есть таблица (с данными), как это:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[lTab](
    [log_id] [int] IDENTITY(1,1) NOT NULL,
    [JobName] [nvarchar](40) NULL,
    [startTime] [datetime] NULL,
    [endTime] [datetime] NULL,
    [BatchId] [int] NULL,
    [status] [varchar](10) NULL,
    [messag] [varchar](255) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[lTab] ON
INSERT [dbo].[lTab] ([log_id], [JobName], [startTime], [endTime], [BatchId], [status], [messag]) VALUES (1, N'Job1', CAST(0x00009EB700FBF56F AS DateTime), NULL, 2, N'START', N'Test')
INSERT [dbo].[lTab] ([log_id], [JobName], [startTime], [endTime], [BatchId], [status], [messag]) VALUES (2, N'Job2', NULL, CAST(0x00009EB700FBF975 AS DateTime), 2, N'START', N'Test')
INSERT [dbo].[lTab] ([log_id], [JobName], [startTime], [endTime], [BatchId], [status], [messag]) VALUES (3, N'Job3', CAST(0x00009EB700FC287F AS DateTime), NULL, 2, N'START', N'Test')
INSERT [dbo].[lTab] ([log_id], [JobName], [startTime], [endTime], [BatchId], [status], [messag]) VALUES (4, N'Job3', NULL, CAST(0x00009EB700FC2CC6 AS DateTime), 2, N'END', N'Test')
SET IDENTITY_INSERT [dbo].[lTab] OFF

Я пытаюсь обновить endTime в зависимости от имени задания и max (log_id).

DECLARE @Jname VARCHAR(10)
SET @Jname = 'Job3'

UPDATE lTab
SET endTime = GETDATE() 
WHERE log_id = (SELECT JobName, MAX(log_id) AS log_id FROM dbo.lTab WHERE jobname = @Jname GROUP BY JobName)

Я получаю ошибку

sg 116, Level 16, State 1, Line 6
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

Как получить эту работу?

Ответы [ 4 ]

3 голосов
/ 31 марта 2011
WITH    q AS
        (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY JobName ORDER BY log_id DESC) AS rn
        FROM    lTab
        WHERE   JobName = @Jname
        )
UPDATE  q
SET     endTime = GETDATE() 
WHERE   rn = 1
2 голосов
/ 31 марта 2011

Извлеките Jobname из списка выбора в подзапросе.

Вам на самом деле это не нужно, чтобы получить нужный результат, SQL Server все равно вернёт правильный log_id.

То, что у вас есть, не будет работать, поскольку вы возвращаете 2 поля (Jobname, MAX(Log_id)) и пытаетесь сопоставить Log_id с ним.

0 голосов
/ 31 марта 2011

Тем не менее, лучшим вариантом будет

UPDATE tablename SET tablename.field1 = sourceTable.dataField
From tablename 
join sourceTable On tablename.keyfield = sourceTable.keyField
Where sourceTable.jobname = @jobName
0 голосов
/ 31 марта 2011

Этот запрос:

(SELECT JobName, MAX(log_id) AS log_id FROM dbo.lTab WHERE jobname = @Jname GROUP BY JobName)

возвращает несколько результатов, исключите JobName из вашего запроса.

...