【问题标题】:How to prevent parameters from VB6 to Oracle using ADO being trimmed如何使用 ADO 防止从 VB6 到 Oracle 的参数被修剪
【发布时间】:2016-06-23 17:11:39
【问题描述】:

我有一个调用 Oracle (12) PL/SQL 存储过程的 VB6 应用程序。它使用 ADODB 连接对象。

从应用程序传递的字符串参数可能有尾随空格。当 Oracle 收到它们时,所有尾随空格都消失了。

我希望保留尾随空格。我到处搜索,但在网上找不到任何关于 VB、ADO 或 Oracle 的行为的参考,这些参考表明应该修剪尾随空格在参数中。

在 Oracle 中,存储过程的参数定义为 varchar2。 在 VB6 中,我使用 CreateParameter() 将参数添加为 adVarChar(我尝试过其他字符串类型,但没有帮助)。调用指定名称、类型、方向、大小和值。

就在执行调用之前,我可以检查 Command.Parameters 集合并验证是否存在任何尾随空格。

Oracle 引用明确指出,对于 varchar2 数据类型,尾随空格不会被忽略。

有人能描述一下 VB 或数据库中是否有导致此问题的选项,并且可以关闭吗?

【问题讨论】:

  • 您能出示您的代码吗?
  • IIRC,尾随空格存储在数据库中,如果您检索该值,它将在那里。 comparisons 忽略它们,即 SQL 语言标准规定在进行 WHERE 子句和 CASE 类型检查时,Foo 等于 Foo
  • 啊,这里有一些关于这个主题的文档。它来自 Sql Server 而不是 Oracle,但它又指的是 ansi 标准,Oracle 可能也遵循该标准(Ansi SQL-92,第 8.2 节,,一般规则 #3)support.microsoft.com/en-us/kb/316626 在 Sql Server 中,您可以通过 LIKE 比较而不是相等比较来解决此问题。不知道 Oracle 是否有相同的行为。
  • 嗨乔尔,我明白你在说什么 RE 比较,但我发现的实际行为是,一旦 sproc 收到空格,参数中就根本不存在空格。我正在立即记录这些值(在测试中),它们就消失了。事实上,我认为 Oracle char 类型如您所描述的那样工作,并且 varchar2 应该设计为不修剪空格(在比较或其他情况下)。

标签: oracle plsql vb6 ado adodb


【解决方案1】:

如果你附加一个空值,它是否有效,即。 chr(0) 到有空格的字符串末尾?

你能展示你传递参数的代码吗?你传递的字符串长度是什么 - 即。你在做 len() 之前做修剪吗?

【讨论】:

  • 我尝试使用 null(实际上它被 chr(0) 阻塞了——我不得不使用 vbNullChar),但它没有任何区别。一旦到达 Oracle,空间就消失了。代码在各种功能中分层,但用于创建参数的删节版本大致是:
  • 'In SetParam ' 创建参数并将其附加到命令对象 ' 假设它是一个输入参数 With mGrid .Col = column ' CreateParameter 阻塞如果长度 = 0,或者如果类型是日期和文本是“”,因此 IIfs cmd.Parameters.Append cmd.CreateParameter(Name, DataType, adParamInput, IIf(Len(.Text) = 0, 1, Len(.Text)), IIf(.Text = "", Null , .Text)) 以'调用它 Grid.SetParam cmd, eColumns.Domain, "pDomain", adVarChar 结尾
  • 如您所见,在通过长度之前没有修剪。我可以在提交之前检查参数对象并且存在空格。
  • 很抱歉格式不佳 - 我正在使用手机完成所有这些操作!
【解决方案2】:

虽然现在我扩展了它,它有资格作为一个解决方案,但仍然没有足够的点来添加评论。

Oracle Objects for OLE (OO4O) 是与现代数据库版本兼容的最佳选择。添加对 oip12.dll 的引用并尝试一下。我的快速测试用例表明,如果我发送 'abc'(即 3 个空格)作为参数,则 sproc 确实保留了尾随空格。我实际上使用的是 oip10.dll 但数据库是 12c。我使用的快速 Oracle 示例。

CREATE TABLE TEMPTestTrailingSpace
 (F1  VARCHAR2(30) NOT NULL
 ,F2   NUMBER(12,0) NOT NULL
 ,DATEIN     DATE NOT NULL
 ) ;

create public synonym TEMPTestTrailingSpace for trace_owner.TEMPTestTrailingSpace;
grant SELECT on TEMPTestTrailingSpace to "TRACE_USER";

Insert into TEMPTestTrailingSpace values ('abc',1,sysdate);
Insert into TEMPTestTrailingSpace values ('abc      ',2,sysdate);
Insert into TEMPTestTrailingSpace values ('abc   ',3,sysdate);
Insert into TEMPTestTrailingSpace values ('abc     ',4,sysdate);
Insert into TEMPTestTrailingSpace values ('abd',5,sysdate);
Insert into TEMPTestTrailingSpace values ('abd   ',6,sysdate);
Insert into TEMPTestTrailingSpace values ('abd    ',7,sysdate);

Create or Replace Procedure getTestRecord
(
  P_PN IN VARCHAR2,
  p_rec OUT number
)
IS
BEGIN
     SELECT f2
     INTO   p_rec
     FROM  TEMPTestTrailingSpace 
     WHERE  f1 = p_pn;
END;
/

create public synonym getTestRecord for trace_owner.getTestRecord;
grant execute on getTestRecord to "TRACE_USER";

我在 db 访问周围使用了一个包装器,因此分享示例并不容易。这至少可以让您建立联系。

Public ooSession As Object
Public ooDB As Object

Dim ConnStr As String
Set ooSession = New OracleInProcServer.OraSessionClass
ConnStr = userID & "/" & password
Set ooDB = ooSession.OpenDatabase(dataSource, ConnStr, 0&) 'dataSource = Oracle SID or alias in TNSNames.ora file

【讨论】:

  • 感谢所有这些细节,并确认有办法做到这一点。我在一个封闭的环境中,所以很遗憾不能在短期内添加 OO4O 作为参考。 (事实上​​,它被锁在这里,我什至无法提交给 Stack Exchange ——这都是通过我的手机完成的!)很高兴知道至少有一些东西可以按我们预期的那样工作。我将研究 OO4O,并在此处请求开发人员可以使用它。
  • 不幸的是,我在经典 VB 中使用的只是 OO4O。当然,有可能使用您正在使用的任何 ADO 提供程序提供解决方案,但我不熟悉这些。就像我所做的那样,很容易组合一个简单的测试来证明事情失败的地方(或者你是否可以成功)。如果您可以访问 ODBC 提供程序,您也可以尝试一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2010-10-11
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多