gpt4 book ai didi

java - zxjdbc调用存储过程的正确用法是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:13:50 25 4
gpt4 key购买 nike

我正在尝试使用zxJDBC连接到在SQL Server 2008 R2(Express)上运行的数据库并调用存储过程,并向其传递单个参数。我正在使用jython-standalone 2.5.3,理想情况下,不想安装其他模块。

我的测试代码如下所示。

数据库名称为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部分包括在内。

如果我改为使用“CSM.dbo.DUMMY”作为第一个参数调用 callproc,那么我会收到此错误
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
  • 正确确定所需的参数
  • 用正确的名称
  • 调用我的存储过程

    都在同一时间。

    我确实有一种解决方法,就是使用类似
    cur.execute('EXEC CSM.dbo.DUMMY ?', ['carrier1'])

    但是,我觉得 callproc()是正确的解决方案,当我使用大量参数调用存储过程时,可能会生成更简洁的代码。

    如果任何人都可以发现我正在犯的错误,或者知道这永远不会奏效,那么我将不胜感激。

    谢谢

    编辑

    根据i-one的建议,我在调用存储过程之前尝试添加 cur.execute('USE CSM')(也从过程调用中删除了数据库名称)。不幸的是,这会产生与上述相同的“对象或列丢失”错误。探查器显示正在执行的 USE CSM,然后显示 USE [],因此似乎callproc()总是在过程本身之前触发 USE语句。

    我也尝试过打开/关闭自动提交,但无济于事。

    编辑2

    以下评论/建议解决方案的更多信息:
  • 我的连接字符串中的“SQLEXPRESS”是数据库实例名称。
  • 使用双引号而不是单引号无效。
  • 在连接字符串中包含数据库名称(通过;databaseName=CSM;指定为here),并将其从callproc()调用中省略会导致原始错误,并触发USE []语句。

  • 使用 callproc(('CSM', 'dbo', 'dbo.DUMMY'), ['carrier1'])给了我一些进步,但会导致错误

    错误(“过程或函数“DUMMY”期望参数“@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没有将任何参数传递给存储过程-它认为不需要。我还没有弄清楚为什么会这样。

    编辑4

    要更新以上内容,结果集为空是因为该调用应为
    exec sp_sproc_columns_100 N'DUMMY',N'dbo',N'CSM',NULL,N'3'

    不幸的是,这使我产生了一个完整的圈子,因为我无法从我的callproc()调用中的存储过程名称中删除 dbo所有者,或者根本找不到该过程。

    编辑5

    根据要求定义表
    CREATE TABLE [dbo].[carrier](
    [carrierId] [varchar](50) NOT NULL,
    [test] [varchar](50) NULL
    ) ON [PRIMARY]

    最佳答案

    尽管完全不了解此处使用的技术(除非对SQL Server有一些了解),但我将尝试给出答案(如果我的jython语法不正确,请原谅我。我试图在此处概述不完全正确的代码的可能性)

    我的第一种方法(位于this post)是尝试:

    cur.execute("use CSM")
    cur.callproc(("CSM","dbo","dbo.DUMMY"), ["carrier1"])

    这必须与 sa用户始终将 dbo作为默认模式有关(在 this SO post中进行了描述)。

    如果以上方法不起作用,我也将尝试在JDBC URL中使用 CSM数据库名称(在将JDBC用于其他数据库时,这是很常见的),然后简单地调用以下两个方法之一。
    cur.callproc("DUMMY", ["carrier1"])
    cur.callproc("dbo.DUMMY", ["carrier1"])

    我希望这有帮助

    更新:我引用了您无法查看的链接的相关部分
    >> Program calls a Stored Procedure - master.dbo.xp_fixeddrives on  MS SQL Server

    from com.ziclix.python.sql import zxJDBC

    def getConnection():
    url = "${DBServer.Url}"
    user= "${DBServer.User}"
    password = "${DBServer.Password}"
    driver = "${DBServer.Driver}"
    con = zxJDBC.connect(url, user, password, driver)
    return con

    try:
    conn = getConnection()
    print 'Connection successful'
    cur = conn.cursor()
    cur.execute("use master")
    cur.callproc(("master", "dbo", "dbo.xp_fixeddrives"))
    print cur.description
    for a in cur.fetchall():
    print a
    finally:
    cur.close()
    conn.close()
    print 'Connection closed'

    如上指定调用函数时收到的错误提示该参数未正确传递。因此,请修改您的存储过程以采用默认值,并尝试通过传递 params = [None]进行调用。如果您看到调用成功,那么就指定数据库而言,我们必须做的正确。
    顺便说一句: most recent documentation建议您应该可以使用自己的语法进行访问。

    关于java - zxjdbc调用存储过程的正确用法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18055993/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com