Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA+ADODB+Oracle中的参数化查询_Vba_Oracle11g_Adodb - Fatal编程技术网

VBA+ADODB+Oracle中的参数化查询

VBA+ADODB+Oracle中的参数化查询,vba,oracle11g,adodb,Vba,Oracle11g,Adodb,我对使用Oracle11g还不熟悉,要使参数化查询顺利工作,我遇到了很多问题 此代码适用于: Dim rs As ADODB.Recordset Dim con As ADODB.Connection Dim cmd As ADODB.Command Dim prm As ADODB.Parameter Set con = New ADODB.Connection With con .ConnectionString = GetC

我对使用Oracle11g还不熟悉,要使参数化查询顺利工作,我遇到了很多问题

此代码适用于:

    Dim rs As ADODB.Recordset
    Dim con As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim prm As ADODB.Parameter

    Set con = New ADODB.Connection
    With con
        .ConnectionString = GetConnection() '<-- the driver here is Driver={Oracle in OraClient11g_home1_32bit}
        .Open
    End With

    Set cmd = New ADODB.Command

    With cmd
        Set .ActiveConnection = con
        .CommandType = adCmdText
        .CommandText = "SELECT * FROM MPA_LINEPLAN.REF_BRAND_SEASON_DROP WHERE DROP_ID = ?" 
        Set prm = .CreateParameter("dropID", adVarChar, adParamInput, 50, "P_SP19_5")
        .Parameters.Append prm
        Set rs = .Execute
    End With
但是当我尝试执行到rs时,它遇到了未指定的错误

另外,对于我的特殊情况,假设存储过程不是最佳选项,即使它应该是最佳选项:-/

编辑: 实际的查询非常长,为了不让您查找所有的:dropID引用,我在这里减少了它,但留下了足够的空间来显示多个引用

WITH 
--...
DropDim AS (
SELECT DROP_ID
     , DROP_NAME
     , SEASON_ID
     , SEASON_NAME
     , BRAND_ID
     , SEASON_YEAR
     , 'DROP_' || substr(DROP_ID, LENGTH(DROP_ID),1) AS LP_Join_Drop
     , SEASON_NAME || '_' || SEASON_YEAR AS LP_Join_Season
FROM MPA_LINEPLAN.REF_BRAND_SEASON_DROP
WHERE DROP_ID = :dropID),
--...
LYMap AS
(SELECT DC.DROP_ID
     , DC.CHANNEL_ID
     , BSD.SEASON_YEAR
     , BSD.SEASON_NAME
     , BSD.DROP_NAME
     , FW.WEEKENDINGDATE  AS LY_WEEKENDING_DATE
     , FW.YEARWEEK AS LY_YEARWEEK
FROM MPA_LINEPLAN.REF_DROP_CHANNEL DC
  INNER JOIN MPA_MASTER.FISCALWEEK FW
    ON FW.YEARWEEK BETWEEN DC.LY_START_DT AND DC.LY_END_DT
  INNER JOIN MPA_LINEPLAN.REF_BRAND_SEASON_DROP BSD ON BSD.DROP_ID = dc.DROP_ID
WHERE DC.DROP_ID = :dropID),

LLYMap AS
(SELECT DC.DROP_ID
     , DC.CHANNEL_ID
     , BSD.SEASON_YEAR
     , BSD.SEASON_NAME
     , BSD.DROP_NAME
     , FW.WEEKENDINGDATE  AS LLY_WEEKENDING_DATE
     , FW.YEARWEEK AS LLY_YEARWEEK
FROM MPA_LINEPLAN.REF_DROP_CHANNEL DC
  INNER JOIN MPA_MASTER.FISCALWEEK FW
    ON FW.YEARWEEK BETWEEN DC.LLY_START_DT AND DC.LLY_END_DT
  INNER JOIN MPA_LINEPLAN.REF_BRAND_SEASON_DROP BSD ON BSD.DROP_ID = dc.DROP_ID
WHERE DC.DROP_ID = :dropID  ),
--....

继续使用qmarks占位符,只需使用for循环来附加相同的参数对象。具体来说,qmark对应于查询中放置的位置。假设下面的查询

sql = "SELECT * FROM MPA_LINEPLAN.REF_BRAND_SEASON_DROP" _
        & " WHERE DROP_ID = ? AND DROP_ID2 = ? AND DROP_ID3 = ?" 

With cmd
   Set .ActiveConnection = con
   .CommandType = adCmdText
   .CommandText = sql
   For i = 1 To 3  ' ADJUST TO NUMBER OF PARAMS
      Set prm = .CreateParameter("prm" & i, adVarChar, adParamInput, 50, "P_SP19_5")
      .Parameters.Append prm
   Next i
   Set rs = .Execute
End With
或者,将查询转换为在VBA中读取的非常大的SQL字符串或文本文件,然后定义一个参数

神谕

创建或替换过程VARCHAR2中的my_PROCEDURE_namedropID为 开始 …使用dropID进行长查询,不带任何符号。。。 终止 / VBA

使用cmd Set.ActiveConnection=con .propertieslsqlrset=TRUE .CommandType=adCmdText .CommandText={调用我的\u过程\u名称} 设置prm=.createParameterTM,adVarChar,adParamInput,50,P_SP19_5 .Parameters.Append prm 设置rs=.Execute 以
最好的解决办法就是停止使用Oracle的ODBC驱动程序,转而使用Oracle的OLEDB作为提供程序

旧连接字符串: .ConnectionString=Driver={OraClient11g_home1_32bit}中的Oracle;UID=MyUname;PWD=MyPW;DBQ=MyDB

新连接字符串: .ConnectionString=Provider=OraOLEDB.Oracle;数据源=MyDB;用户ID=MyUname;密码=MyPW

OraOLEDB支持命名参数,这正是我一开始想要得到的。现在,我可以使用:prefix引用SQL语句中的参数名称


现在可以了

另一种方法是使用CTE获取所有标量参数,然后连接回您感兴趣的表:

-由于VBA中ODBC驱动程序的限制,外部选择* 挑选* 从…起 以卢为首 选择作为投递id 来自双重 选择t1* 来自mpa_lineplan.ref_brand_season_drop t1 交叉连接lu-可以是内部连接,也可以是您感兴趣的任何类型 其中t1.drop\u id=lu.drop\u id
声明一个变量?设置@foo=?然后在脚本中使用@foo?IDK关于Oracle,但这可能是我在SQL Server上所做的。@MathieuGuindon我也会这么想,但我尝试的Oracle等价物似乎都不起作用。我得到了各种各样的变量绑定错误。令人惊讶的是,我在网上找不到任何有效的例子:-我不理解这个问题。其中,我们反复使用相同的参数。为什么qmarks不起作用?在两个准备好的语句中,只使用一个参数。你是说一个包含多个qmark的SQL语句吗?@Parfait为了简单起见,我只放了一个简单的SQL语句。实际语句引用dropID或qmark变量10次以上。关键是,我不想添加相同的参数10次以上,以使qmark版本工作。在同一个SQL查询中多次?请使用不止一个dropID引用来显示实际值。这是可行的,但如果/当您开始需要另一个参数时,会很快变得混乱。我想我从未使用过它们,但ADODB不支持命名参数吗?@MathieuGuindon,不幸的是不支持。但是我添加了一个OP可以考虑的存储过程版本哈!删除我的草稿然后-将与推荐一个存储过程一起。。。用VBA或任何语言编写SQL时,哪一种应该是首选的方法?真的吗?谢谢你的建议。我公司的DBA使开发存储过程变得很困难,我必须经历一个官僚过程才能完成简单的DDL,即使对于开发人员也是如此。事实上,我找到了另一个更好的解决方案。我将发布它,以防其他人偶然发现同样的问题,但我只是想感谢你花时间回答我的问题!使用cmd.NamedParameters=True重新尝试不带循环但带有:dropID的ODBC版本。有趣!但再一次,您的示例只使用了一个参数。这是否适用于包含多个:dropID的较大查询?请在回答中提及。是的,这适用于对同一参数变量的多个引用。我将用一个更好的例子来更新我的答案。你的例子实际上与大约10年前OraOleDB只支持位置绑定而不支持命名参数的说法背道而驰。不过,这可能是OLEDB提供程序的版本问题。@Parfait好吧,您是对的,先生。我跳枪了——oraOLEDB即使在这种情况下也在使用位置绑定。头撞在桌子上
sql = "SELECT * FROM MPA_LINEPLAN.REF_BRAND_SEASON_DROP" _
        & " WHERE DROP_ID = ? AND DROP_ID2 = ? AND DROP_ID3 = ?" 

With cmd
   Set .ActiveConnection = con
   .CommandType = adCmdText
   .CommandText = sql
   For i = 1 To 3  ' ADJUST TO NUMBER OF PARAMS
      Set prm = .CreateParameter("prm" & i, adVarChar, adParamInput, 50, "P_SP19_5")
      .Parameters.Append prm
   Next i
   Set rs = .Execute
End With
With cmd
    Set .ActiveConnection = con
    .CommandType = adCmdText
    .CommandText = "SELECT * FROM MPA_LINEPLAN.REF_BRAND_SEASON_DROP WHERE DROP_ID =:dropID"
    Set prm = .CreateParameter("dropID", adVarChar, adParamInput, 50, "P_SP19_5")
    .Parameters.Append prm
    Set rs = .Execute
End With