为什么参数序列在SQL中很重要

为什么参数序列在SQL中很重要,sql,oracle,Sql,Oracle,我认为这是入门级的,但我还没有用谷歌搜索出任何答案 在构建查询时,我们是否必须使用:1,:2。。。按绝对顺序排列的东西?从我的测试来看,似乎是的。但是调用stmt->setXXX(n,val)不就是用val设置语句中的第n个参数吗?它是如何实施的 请参见下面的示例: if (bNewContent) //new { sql = "BEGIN PackProductManagement.procAddOTTContent(:1, :2, :3, :4, :5,

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

在构建查询时,我们是否必须使用: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,因此我们始终运行update语句。上面的查询工作正常。但是如果我像下面这样更改更新查询(在update语句的开头删除
ContentID=:1,
),我将得到一个ORA-01722无效的\u编号。为什么我不能: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的回答)

以上代码不适用于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个参数。

答案是,这取决于

sql = "UPDATE OTT_Content SET ContentID = :1 ContentType = :x, FingerPrint = :x, IsHighLevelSafe = :x, ";
sql += "OutProtection = :x, OfflinePlayback = :x, ModifyTime = sysdate ";
sql += "WHERE ContentID = :1";
如果使用.net和odbc,则必须使用位置参数。如果您使用的是.net和sql server,则可以使用命名参数。如果在ColdFusion中使用cfstoredproc标记,则必须使用位置参数

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

根据bind,变量是按照它们的放置顺序使用的,而不是它们的命名方式。这就是为什么你会得到一个例外。因此,您只需要按照提到的顺序设置参数(在删除第一个参数的情况下,首先提到的是
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);
}

嗯。这在SQL中并不重要。这在Oracle中可能很重要……但至少SQL Server和Postgres可以实际命名它们的参数。这个
:1
垃圾是给鸟的PI收回这一点…PostgreSQL实际上执行
$1
$2
等操作。但是文档中没有说明必须按顺序使用它们。您使用的是哪种驱动程序?按名称/位置绑定的行为各不相同,但这里它显然是按位置绑定的,参数的“名称”被忽略<代码>:1在此上下文中是名为
1
的参数,而不是参数1。(您没有
:7
,但您使用的是
setXXX(7,…)
。@Alex感谢您的解释!我正在SUSE机器上运行Oracle(11gR1)。。我试着用lsmod检查司机,但不确定我应该看哪一个。(7是有条件的,在Update语句中没有使用)哦,是的,我注意到7没有使用,然后忘记了,对不起。我以前回答过这样一个问题(类似于ZZa的回答),但由于某种原因找不到。看起来有点奇怪的是第二次引用
:1
有效。谢谢@Dan!我正在用oracle DB在linux上运行测试,有什么详细的文档可以学习吗?我只找到了关于setXXXs的信息,但它没有说明任何关于该职位的信息。非常感谢。你说得对!通过进一步的测试,结果证明代码中调用setXXX的顺序(这里是C++)并不重要,但是setXXX中的n(n,val)必须与查询中提到的顺序匹配。此外,似乎出于某种原因,DB在WHERE子句中将部分参数名称视为“name”,因为WHERE中的
:1
在我的测试中被替换(请参阅更新的帖子…)。我们将NET integrated Oracle驱动程序转换为托管(nuget)。该应用程序不断抛出ORA-1722而不是一个数字。阅读本文后,我们意识到在TSQL中完全忽略了参数中的第一个参数(索引)和“名称”。非常感谢你指出这一点。更新了到v19的链接。