Я пытаюсь использовать zxJDBC для подключения к базе данных, работающей на SQL Server 2008 R2 (Express), и вызвать хранимую процедуру, передав ей один параметр. Я использую jython-standalone 2.5.3 и в идеале не хочу устанавливать дополнительные модули.Какое правильное использование zxjdbc для вызова хранимых процедур?
Мой тестовый код показан ниже.
имя базы данных CSM
хранимых процедур:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE dbo.DUMMY
-- Add the parameters for the stored procedure here
@carrierId VARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO dbo.carrier (carrierId, test)
VALUES (@carrierId, 'Success')
END
GO
Jython Сценарий:
from com.ziclix.python.sql import zxJDBC
conn = None
try :
conn = zxJDBC.connect('jdbc:sqlserver://localhost\SQLEXPRESS', 'sa', 'password', 'com.microsoft.sqlserver.jdbc.SQLServerDriver')
cur = conn.cursor()
cur.callproc(('CSM','dbo','DUMMY'), ['carrier1'])
conn.commit()
except Exception, err :
print err
if conn:
conn.rollback()
finally :
if conn :
conn.close()
С помощью cur.execute()
я смог убедиться, что выше успешного подключения к базы данных, и я могу запросить его. Однако до сих пор мне не удалось успешно вызвать хранимую процедуру с параметрами.
Документация here (возможно, устаревшая?) Указывает, что callproc()
может быть вызвана либо строкой, либо кортежем для идентификации процедуры. Данный пример -
c.callproc(("northwind", "dbo", "SalesByCategory"), ["Seafood", "1998"], maxrows=2)
При попытке использовать этот метод, я получаю следующую ошибку
Error("Could not find stored procedure 'CSM.DUMMY'. [SQLCode: 2812], [SQLState: S00062]",)
Казалось бы, что zxJDBC пренебрегает включить dbo
часть идентификатора процедуры.
Если я вместо этого позвонить callproc
с «CSM.dbo.DUMMY» в качестве первого аргумента, то я получаю эту ошибку
Error('An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. [SQLCode: 1038], [SQLState: S0004]',)
с использованием профилировщика в базе данных в то время как работает мой сценарий показывает, что во втором случае следующий SQL выполняется:
use []
go
Так что, казалось бы, что при использовании одной строки, чтобы определить процедуру, имя базы данных не правильно разобран вне.
Один из моих проб и ошибок попытки исправить это назвать callproc следующим образом:
cur.callproc(('CSM', '', 'dbo.DUMMY'), ['carrier1'])
Это заставило меня настолько, насколько
Error("Procedure or function 'DUMMY' expects parameter '@carrierId', which was not supplied. [SQLCode: 201], [SQLState: S0004]",)
В этом случае то, что я думаю происходит то, что zxJDBC пытается вызвать системную хранимую процедуру (sp_proc_columns
), чтобы определить требуемые параметры для хранимой процедуры, которую я хочу вызвать. Я предполагаю, что с идентификатором процедуры в неправильном формате выше, zxJDBC не получает действительный/правильный возврат и не предполагает, что параметры не требуются.
Поэтому в основном я не немного застряли для идей о том, как получить его
- Используйте правильное имя базы данных
- правильно определить требуемые параметры с помощью sp_proc_columns
- Call My хранимой процедуры правильное название
все в то же время.
У меня есть обходной путь, который должен использовать что-то вроде
cur.execute('EXEC CSM.dbo.DUMMY ?', ['carrier1'])
Однако я чувствую, что callproc()
является правильным решением, и, скорее всего, производить чистый код, когда я пришел, чтобы вызывать хранимые процедуры с большим количеством параметры.
Если кто-нибудь может определить ошибки, которые я делаю, или знает, что это никогда не будет работать, как я думаю, тогда любой вклад был бы высоко оценен.
Благодаря
Редактировать
Как предложенное я-один, я попытался добавить cur.execute('USE CSM')
перед вызовом моей хранимой процедуры (также удаление имени базы данных из процедуры вызова). Это, к сожалению, приводит к тому, что ошибка объекта или столбца отсутствует, как указано выше. Профайлер показывает USE CSM
, а затем USE []
, поэтому кажется, что callproc() всегда запускает инструкцию USE
перед самой процедурой.
Я также экспериментировал с включением/выключением autocommit, но безрезультатно.
Edit 2
Дополнительная информация Следующие комментарии/Предлагаемые решения:
- "SQLEXPRESS" в моей строке соединения это имя экземпляра базы данных.
- Использование двойных кавычек вместо одиночного не влияет.
- Включая имя базы данных в строку подключения (через
;databaseName=CSM;
, как указано here), и опускает ее из вызова callproc(), приводит к исходной ошибке с запущенным операторомUSE []
.
Использование callproc(('CSM', 'dbo', 'dbo.DUMMY'), ['carrier1'])
дает мне некоторый прогресс, но приводит к ошибке
Error ("Процедура или функция„пустышки“ожидает параметр„@carrierId“, который не поставлялся.[SQLCODE: 201], [SQLState: S0004]»,)
Я попытаюсь исследовать это еще больше
Редактировать 3
Основываясь на запросах я мог видеть zxJDBC стрельбы, я вручную выполнены следующие против моей базе данных:.
use CSM
go
exec sp_sproc_columns_100 N'dbo.DUMMY',N'dbo',N'CSM',NULL,N'3'
go
Это дало мне пустой набор результатов, которые, казалось бы объяснить, почему zxJDBC не проходит никаких параметров хранимой процедуры - это не думаю, что это нужно мне еще чтобы понять, почему это происходит.
Edit 4
Для обновления выше, пустой набор результатов, потому что вызов должен быть
exec sp_sproc_columns_100 N'DUMMY',N'dbo',N'CSM',NULL,N'3'
К сожалению, это приносит мне полный круг, как я не могу удалить dbo
владельца от имя хранимой процедуры в вызове callproc() или процедура не будут найдены вообще.
Редактировать определение 5
Таблицы по запросу
CREATE TABLE [dbo].[carrier](
[carrierId] [varchar](50) NOT NULL,
[test] [varchar](50) NULL
) ON [PRIMARY]
На самом деле я не испытал, чтобы ответить, я просто вижу, что время баунти выходит, и вы наедине с вашей проблемой. Одна вещь, которую я заметил в документах zxjdbc. Не могли бы вы попытаться следовать? После запуска курсора (после 'cur = conn.cursor()') попробуйте 'c.execute (« использовать CSM »)' (это должно переключить контекст из базы данных 'master' в' CSM' и разрешить ссылку на объекты db без имени db prefix), а затем попробуйте 'cur.callproc (" dbo.DUMMY ", [" carrier1 "])' или даже 'cur.callproc (" DUMMY ", [" carrier1 "])'. Что произойдет, если вы это сделаете? –
@ i-one Спасибо за предложение. Мне не повезло с этим, я боюсь, но отредактировал вопрос с описанием результата – Vindicare
Может быть 'cur.callproc (('CSM', '', 'dbo.DUMMY?'), [' operator1 ']) 'или' cur.callproc ((' CSM ',' ',' dbo.DUMMY @carrierId '), [' carrier1 ']) '? –