Каков наилучший способ обновить одну запись через SQL и получить идентификатор записи, которая была обновлена? (Java / MSSQL) - PullRequest
0 голосов
/ 09 декабря 2008

Я знаю, что могу обновить одну запись, как это - но тогда как мне получить доступ к идентификатору записи, которая была обновлена? (Я использую MSSQL, поэтому я не могу использовать Oracles RowId)

update myTable
set myCol = 'foo'
where itemId in (select top 1 itemId from myTable )

Если бы я выполнял вставку, я мог бы использовать getGeneratedKeys, чтобы получить значение поля id, но я не думаю, что для обновления есть эквивалент?

Я знаю, что могу использовать прокручиваемый набор результатов, чтобы делать то, что я хочу

т.е.

stmt = conn.prepareStatement("select top 1 myCol, itemId from myTable", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet resultSet = stmt.executeQuery();
if(resultSet.first()){
    resultSet.updateString(1, "foo");
    resultSet.updateRow();
    String theItemId = resultSet.getString(1)
}
resultSet.close();

но меня беспокоит производительность, так как тестирование показывает таймауты блокировки под нагрузкой, и мне было интересно, есть ли лучший / более простой способ?

- РЕДАКТИРОВАТЬ: Просто, чтобы завершить эту проблему ... Когда мы перейдем на MSSQL2005, мы обновим наш код, чтобы использовать ответ Рича. В текущем выпуске мы использовали подсказки блокировки: (UPDLOCK ROWLOCK READPAST), чтобы уменьшить проблемы с производительностью, которые показал наш оригинальный код.

Ответы [ 4 ]

6 голосов
/ 09 декабря 2008

Этот пример очень хорошо работает в MSSQL 2005 ...

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

DROP TABLE [dbo].[TEST_TABLE]
GO

CREATE TABLE [dbo].[TEST_TABLE](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
 CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


-- An insert which will return the identity
INSERT INTO [dbo].[TEST_TABLE] ([name]) 
OUTPUT inserted.id
VALUES('Test 1')

-- Another insert which will return the identity
INSERT INTO [dbo].[TEST_TABLE] ([name]) 
OUTPUT inserted.id
VALUES('Test 2')

-- Now an update which will return the identity
UPDATE [dbo].[TEST_TABLE]
SET [name] = 'Updated Test 1'
OUTPUT inserted.id
WHERE [name] = 'Test 1'

SELECT id, [name] FROM [dbo].[TEST_TABLE]

А точнее к вашему запросу ...

update myTable
set myCol = 'foo'
output inserted.itemid
where itemId in (select top 1 itemId from myTable )
0 голосов
/ 09 декабря 2008

Должно ли это быть в одном утверждении? В конечном итоге это будет лучше всего в качестве хранимой процедуры

Create Procedure doMyUpdate

 @Id int output

as

Set @Id = (select top 1 itemId from myTable)
update myTable
set myCol = 'foo'
where itemId = @Id

другим способом было бы использовать ключевое слово RETURN и встроенный параметр RETURN_VALUE ...

Create Procedure doMyUpdate

as

Declare @Id int
Set @Id = (select top 1 itemId from myTable)

update myTable
set myCol = 'foo'
where itemId = @Id

RETURN @Id
0 голосов
/ 09 декабря 2008

Я бы сделал следующее:

Begin Tran

update myTable
set myCol = 'foo'
where itemId in (select top 1 itemId from myTable )

select top 1 itemId from myTable

Commit Tran
0 голосов
/ 09 декабря 2008

Для вставки MSQSQL сервер имеет параметр @@Identity, который имеет идентификатор последней вставленной записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...