4

我认为这是入门级的,但我没有用谷歌搜索任何答案..

在构建查询时,我们是否必须以绝对顺序使用 :1, :2... 的东西?从我的测试来看,似乎是的。但是调用 stmt->setXXX(n, val) 不只是用 val 设置语句中的第 n 个参数吗?它是如何实施的?

请看下面我的例子:

    if (bNewContent)    //new
    {
        sql = "BEGIN PackProductManagement.procAddOTTContent(:1, :2, :3, :4, :5, :6, :7); END; ";
    }
    else                //update
    {
        sql = "UPDATE OTT_Content SET ContentID = :1, ContentType = :2, FingerPrint = :3, IsHighLevelSafe = :4, ";
        sql += "OutProtection = :5, OfflinePlayback = :6, ModifyTime = sysdate ";
        sql += "WHERE ContentID = :1";
    }
    try
    {
        OpenStatement(sql);
        stmt->setString(1, ac->ContentDesc.ContentID);
        stmt->setUInt(2, ac->ContentDesc.ContentType);
        stmt->setUInt(3, ac->ContentDesc.FingerPrint);
        stmt->setUInt(4, ac->ContentDesc.HighLevelSafe);
        stmt->setUInt(5, ac->ContentDesc.OutputProtection);
        stmt->setUInt(6, ac->ContentDesc.OfflinePlayback);
        if (bNewContent)
        {
            stmt->setUInt(7, 0);        //only used if new
        }
        stmt->execute();

        CloseStatement(true);
    }

在此示例中,bNewContent始终为 FALSE,因此我们始终运行更新语句。上面的查询工作正常。但是,如果我像下面这样更改更新查询(ContentID = :1,在更新语句的开头删除),我将得到 ORA-01722 INVALID_NUMBER。为什么我不能:2:3:4:5:6:1?如果 setXXX 像队列一样实现,为什么上面的 :1:2:3:4:5:6:1 工作?

sql = "UPDATE OTT_Content SET  ContentType = :2, FingerPrint = :3, IsHighLevelSafe = :4, ";
sql += "OutProtection = :5, OfflinePlayback = :6, ModifyTime = sysdate ";
sql += "WHERE ContentID = :1";

提前致谢!

编辑:

下面的测试结果:(基于ZZa的回答)

sql = "UPDATE OTT_Content SET ContentID = :x ContentType = :x, FingerPrint = :x, IsHighLevelSafe = :x, ";
sql += "OutProtection = :x, OfflinePlayback = :x, ModifyTime = sysdate ";
sql += "WHERE ContentID = :x";

上面的代码不适用于 6 个参数。

sql = "UPDATE OTT_Content SET ContentID = :1 ContentType = :x, FingerPrint = :x, IsHighLevelSafe = :x, ";
sql += "OutProtection = :x, OfflinePlayback = :x, ModifyTime = sysdate ";
sql += "WHERE ContentID = :1";

上面的代码使用 6 个参数。

4

2 回答 2

4

根据ORACLE 文档,绑定变量是按照它们放置的顺序使用的,而不是它们的命名方式。这就是为什么你会得到一个例外。所以,你只需要按照它们被提到的顺序设置参数(第一个提到的是ContentType你删除第一个的情况),它们的命名方式并不重要。

您的代码可能看起来像这样,它仍然可以正常工作:

if (bNewContent)    //new
{
    sql = "BEGIN PackProductManagement.procAddOTTContent(:x, :x, :x, :x, :x, :x, :x); END; ";
}
else                //update
{
    sql = "UPDATE OTT_Content SET ContentID = :x, ContentType = :x, FingerPrint = :x, IsHighLevelSafe = :x, ";
    sql += "OutProtection = :x, OfflinePlayback = :x, ModifyTime = sysdate ";
    sql += "WHERE ContentID = :x";
}
try
{
    OpenStatement(sql);
    stmt->setString(1, ac->ContentDesc.ContentID);
    stmt->setUInt(2, ac->ContentDesc.ContentType);
    stmt->setUInt(3, ac->ContentDesc.FingerPrint);
    stmt->setUInt(4, ac->ContentDesc.HighLevelSafe);
    stmt->setUInt(5, ac->ContentDesc.OutputProtection);
    stmt->setUInt(6, ac->ContentDesc.OfflinePlayback);
    if (bNewContent)
    {
        stmt->setUInt(7, 0);        //only used if new
    }
    stmt->execute();

    CloseStatement(true);
}
于 2013-05-15T08:36:33.413 回答
2

答案是,这取决于。

如果您使用的是 .net 和 odbc,则必须使用位置参数。如果您使用的是 .net 和 sql server,则可以使用命名参数。如果您在 ColdFusion 中使用 cfstoredproc 标记,则必须使用位置参数。

等等等等。

于 2013-05-15T02:06:39.113 回答