Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Как бороться с ошибкой при вставке в таблицу с identity ключом:
com.microsoft.sqlserver.jdbc.SQLServerException: Результирующий набор создан для обновления.

Подробности в этой теме hibernate + mssql identity
Если кратко, то ситуация такая:
2 одинаковых сервера, на одном вставка (обычный insert) работает, на другом получаю ошибку, описанную выше. Насколько я понимаю, сервер вместо количества вставленных строк возвращает набор данных, что вызывает ошибку в драйвере.

Триггеров в таблице нет.

Модератор: Тема перенесена из форума "Microsoft SQL Server".

Модератор: Тема перенесена из форума "Java".


Сообщение было отредактировано: 22 окт 15, 16:35
22 окт 15, 16:11    [18312846]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8815
ivanra,

сервер не возвращает данные при вставке с таблицу, если для таблицы не определен специфический триггер. Сервер может вернуть драйверу текстовое сообщение о количестве обработанных строк, драйвер может превратить это сообщение в объект набора строк. Чтобs сервер вел себя тихо, для каждого нового соединения необходимо передавать команду SET NOCOUNT ON.

Если триггера нет и нет ошибки, то я не знаю, как объяснить такое поведение при SET NOCOUNT ON.
22 окт 15, 17:34    [18313350]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
на другом сервере - работает, в чем различие непонятно, версия серверов одинаковая.
Видимо, какая-то ошибка в драйвере sqljdbc4, но исходников нет, посмотреть невозможно.

Попробовал драйвер jtds (http://jtds.sourceforge.net/) - заработало как положено. Видимо, на этом и остановлюсь
22 окт 15, 17:50    [18313449]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Видимо, какая-то ошибка в драйвере sqljdbc4, но исходников нет, посмотреть невозможно.

Смотреть надо в Профайлере все команды, которые отсылает ваша программа серверу.
Прямо с установки соединения.
23 окт 15, 09:21    [18315107]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Серверу посылается обычный prepared-запрос на вставку:
insert into Order(...тут все поля кроме order_id) values ?,?,?,...

Вопрос в том, что сервер возвращает.
Я тут подумал - он ведь действительно кроме отчета о вставке записи должен вернуть и саму запись, иначе как клиент узнает о присвоенном значении identity? Ну или что он там возвращает - тут знатоки должны знать.
В hibernate это выглядит так:
insert.executeUpdate(); // сводится к методу драйвера executeUpdate
...
ResultSet rs = GetGeneratedKeysHelper.getGeneratedKey(insert); // тут вызывается метод драйвера "getGeneratedKeys"
... дальше извлечение поля identity из rs

Проблема, что в драйвере возникает ошибка на первой строчке.

Да, нашел различие в серверах - ошибка была при работе с 32-разрядным. Может, в этом причина? При этом клиент 32-разрядный
23 окт 15, 11:55    [18315975]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Серверу посылается обычный prepared-запрос на вставку:

Вы разницу между "я написал в своем клиентском коде" и "сервер получил" понимаете ?

ivanra
Вопрос в том, что сервер возвращает.

Не сервер решает, что ему возвращать
23 окт 15, 11:57    [18315995]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Чисто логически - в данном случае важно как раз то, что сервер вернул.
Я же написал выше - 2 одинаковых сервера, клиент один и тот же, команда элементарная - вставить запись в таблицу с identity ключом.
Запись при этом вставляется и там, и там, ошибка возникает при обработке ответа драйвером.
Отличие серверов нашел только в том, что один 64 разрядный (ошибок нет), другой - 32 (ошибка).

Разве могут в описанных условиях сервера получать разные данные?
23 окт 15, 12:12    [18316080]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Чисто логически - в данном случае важно как раз то, что сервер вернул.

Еще раз. Сервер возвращает то, что ему указано было возвращать.

ivanra
Я же написал выше - 2 одинаковых сервера, клиент один и тот же, команда элементарная - вставить запись в таблицу с identity ключом.
Запись при этом вставляется и там, и там, ошибка возникает при обработке ответа драйвером.
Отличие серверов нашел только в том, что один 64 разрядный (ошибок нет), другой - 32 (ошибка).

Вы хоть 100 раз это напишите. Это не заменит трассировки команд, которые получил сервер.

ivanra
Разве могут в описанных условиях сервера получать разные данные?

Серверы не пишут команды сами себе. Хоть они 64битные, хоть 32битные.
Полностью идентичные набор команд продуцирют одинаковые результаты.
Набор команд - это _все_команды, а не какой-нибудь один последний insert
23 окт 15, 12:18    [18316111]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
ivanra,

Ошибка в вашем кибернейте, драйвер тут вряли при делах, смотрите какие команды генерирует ваш кибер при GetGeneratedKeysHelper.getGeneratedKey(insert), там и проблема. Искуственный интеллект однако:)
23 окт 15, 12:55    [18316324]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Почти угадал причину Владислав Колосов, только надо было наоборот:
SET NOCOUNT OFF
26 окт 15, 09:16    [18325195]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Почти угадал причину Владислав Колосов, только надо было наоборот:
SET NOCOUNT OFF

Только вот эти настройки задает клиентский код
26 окт 15, 09:20    [18325209]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Это был код в другом приложении, но оба приложения использовали один и тот же источник данных.
Но фактически, ошибка именно в драйвере. При установленном "SET NOCOUNT ON" родной драйвер sqljdbc4.jar выдает ошибку при вставке записи, opensource драйвер jtds-1.3.1.jar отрабатывает как положено.
26 окт 15, 09:48    [18325342]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Это был код в другом приложении, но оба приложения использовали один и тот же источник данных.
Но фактически, ошибка именно в драйвере. При установленном "SET NOCOUNT ON" родной драйвер sqljdbc4.jar выдает ошибку при вставке записи, opensource драйвер jtds-1.3.1.jar отрабатывает как положено.

Для того, чтобы заявлять об ошибке вы должны
- знать, как влияет на выполнение серверного кода настройка SET NOCOUNT
- знать, как разработчик драйвера реализовал использование этой настройки в своем коде
26 окт 15, 09:52    [18325382]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Я считаю, серверная настройка не должна влиять на поведение клиента. В конце концов, все эти odbc,jdbc и прочее как раз и придуманы для того, чтобы можно было стандартизировать взаимодействие серверной и клиентской части. И если клиент начинает вести себя нестандартно, в зависимости от отправленной на сервер команды, это ошибка.
Вот код для проверки.
Таблица:
CREATE TABLE [dbo].[TestTable](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[comment] [varchar](50) NULL
)

Клиентский код
private static final String con_sqljdbc = ... // строка подключения с драйвером sqljdbc
private static final String con_jtds = ... // строка подключения с драйвером jtds

public static void main(String[] args) throws ClassNotFoundException, SQLException {
	Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
	Class.forName("net.sourceforge.jtds.jdbc.Driver");
	
	Connection con = DriverManager.getConnection(con_jtds); //или con_sqljdbc
	PreparedStatement insert = null;
	ResultSet rs = null;
	try {
		con.createStatement().execute("set NOCOUNT on");
		insert = con.prepareStatement(
				"insert into TestTable(comment) values (?)",
				Statement.RETURN_GENERATED_KEYS );
		insert.setString(1, "test");
		insert.executeUpdate(); // со строкой подключения con_sqljdbc валится
		// 
		rs = insert.getGeneratedKeys();
		rs.next();
		System.out.println(rs.getInt(1)); // возвращенное значение identity
	} finally {
		if (rs!=null) rs.close();
		if (insert!=null) insert.close();
		con.close();
	}
}
26 окт 15, 10:09    [18325496]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Я считаю, серверная настройка не должна влиять на поведение клиента.

Ага. Вообще никакие настройки не должны на что-нибудь влиять.

ivanra
В конце концов, все эти odbc,jdbc и прочее как раз и придуманы для того, чтобы можно было стандартизировать взаимодействие серверной и клиентской части. И если клиент начинает вести себя нестандартно, в зависимости от отправленной на сервер команды, это ошибка.

Для того, чтобы говорить о несоблюдении стандартов, нужно как минимум знать эти стандарты.
26 окт 15, 10:30    [18325645]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Glory
Для того, чтобы говорить о несоблюдении стандартов, нужно как минимум знать эти стандарты.

Glory,
если вы не знаете, в java стандарты описываются интерфейсами. Вся документация присутствует в jdk и в интернете.
Вот описание метода PreparedStatement.executeUpdate()
В частности, описано, в каких случаях выкидывается SQLException (а у нас его наследник - SQLServerException). В соответствии с дополнительным описанием ошибки "Результирующий набор создан для обновления" мы попали на случай "SQL statement returns a ResultSet object". С какой стати?
1) у нас insert - выражение, оно не должно возвращать набор данных. Точно известно, что у таблицы нет никаких триггеров. DDL я привел.
2) Может, что-то есть в описании SET NOCOUNT? "Если значение инструкции SET NOCOUNT равно ON, то количество строк не возвращается." - тут тоже ничего про возвращаемый набор данных

Таким образом и заключаем, что метод интерфейса PreparedStatement.executeUpdate() в драйвере sqljdbc реализован некорректно
26 окт 15, 11:33    [18326009]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
2) Может, что-то есть в описании SET NOCOUNT? "Если значение инструкции SET NOCOUNT равно ON, то количество строк не возвращается." - тут тоже ничего про возвращаемый набор данных

Гы-гы. Вы думаете, что количество строк возвращается каким-то "магическим" способом ?
Тогда не тыкайте в документацию, а читайте ее сначала.

ivanra
Таким образом и заключаем, что метод интерфейса PreparedStatement.executeUpdate() в драйвере sqljdbc реализован некорректно

Один мой знакомый знает, как решить все экономические проблемы страны. Но ему некогда - надо таксовать.
26 окт 15, 11:36    [18326021]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Glory
ivanra
2) Может, что-то есть в описании SET NOCOUNT? "Если значение инструкции SET NOCOUNT равно ON, то количество строк не возвращается." - тут тоже ничего про возвращаемый набор данных

Гы-гы. Вы думаете, что количество строк возвращается каким-то "магическим" способом ?
Тогда не тыкайте в документацию, а читайте ее сначала.

"количество строк не возвращается" не подразумевает никаких магических способов. Всё-таки посмотрите документацию PreparedStatement.executeUpdate(). Если SQL выражение ничего не вернуло, метод должен вернуть 0, а не валиться в исключение.
Впрочем, если у Вас есть другая информация, приведите ссылку
26 окт 15, 12:24    [18326358]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Если SQL выражение ничего не вернуло, метод должен вернуть 0, а не валиться в исключение.
Впрочем, если у Вас есть другая информация, приведите ссылку

Гы-гы 2.
Ну так откуда вы знаете то, чего и сколько вернуло "SQL выражение" ?
Вы же ничего не мониторили.
26 окт 15, 12:29    [18326386]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
ivanra,

Странный вы, сначала отключили вывод информации сервером, а потом ругаете его, что он вам не сообщает информацию:)
Интересно, по вашей логике, если сервер вообще выключить, то метод все равно должен прислать количество обработанных строк, да?
26 окт 15, 12:52    [18326542]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
ivanra
Member

Откуда:
Сообщений: 889
Я вижу, тут в основном одни писатели собрались, читать никто не хочет. Ну давайте, знатоки, растолкуйте лог. java код я привел выше
С драйвером jtds, работает
+ Audit Login
-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
+ SQL:BatchStarting
SELECT @@MAX_PRECISION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SET IMPLICIT_TRANSACTIONS OFF
SET QUOTED_IDENTIFIER ON
SET TEXTSIZE 2147483647
+ SQL:BatchCompleted
SELECT @@MAX_PRECISION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SET IMPLICIT_TRANSACTIONS OFF
SET QUOTED_IDENTIFIER ON
SET TEXTSIZE 2147483647
+ SQL:BatchStarting
set NOCOUNT on
+ SQL:BatchCompleted
set NOCOUNT on
+ RCP:Completed

declare @p1 int
set @p1=1
exec sp_prepare @p1 output,N'@P0 nvarchar(4000)',N'insert into Tisio.dbo.TestTable(comment) values ( @P0 ) SELECT SCOPE_IDENTITY() AS _JTDS_GENE_R_ATED_KEYS_',1
select @p1
+ RCP:Completed
exec sp_execute 1,N'test'
+ Audit Logout


С драйвером sqljdbc, валится
+ Audit Login
-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
+ SQL:BatchStarting
set NOCOUNT on
+ SQL:BatchCompleted
set NOCOUNT on
+ RCP:Completed
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P0 nvarchar(4000)',N'insert into Tisio.dbo.TestTable(comment) values (@P0)         select SCOPE_IDENTITY() AS GENERATED_KEYS',N'test'
select @p1
+ RCP:Completed
exec sp_unprepare 1
+ Audit Logout
26 окт 15, 13:56    [18327109]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Glory
Member

Откуда:
Сообщений: 104751
ivanra
Я вижу, тут в основном одни писатели собрались, читать никто не хочет.

Конечно. Но вы пришли и сейчас все изменится.

ivanra
Ну давайте, знатоки, растолкуйте лог. java код я привел выше

Для разбора java code есть свой профильный форум

ivanra
С драйвером sqljdbc, валится

Где показано, что "SQL выражение ничего не вернуло" ? И что вообще вернули "sql выражения"
Куда, например, делся делся результат SELECT @@MAX_PRECISION ? А select @p1 ?
И почему разница в PRC:Completed ?
26 окт 15, 14:09    [18327195]     Ответить | Цитировать Сообщить модератору
 Re: jdbc: ошибка при вставке с identity ключом  [new]
Konst_One
Member

Откуда:
Сообщений: 11621
ivanra
С драйвером sqljdbc, валится


ну так у вас тут нет выполнения как такового, тут попытка получить формат вывода ответа , но это может не работать , зависит от клиентских настроек соединения SET FMTONLY
26 окт 15, 15:25    [18327836]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить