ODBC参数占位符可以命名吗?

我做了一些搜索,但没有找到我的问题的确切答案。

有没有办法定义哪个? 在SQL查询中属于哪个参数?
例如,我需要执行以下操作:

 SELECT * FROM myTable WHERE myField = @Param1 OR myField2 = @Param1 OR myField1 = @Param2 OR myField2 = @Param2 

ODBC的相同查询是:

 SELECT * FROM myTable WHERE myField = ? or myField2 = ? or myField1 = ? or myField2 = ? 

有没有办法告诉ODBC命令哪个参数除了为每个值加载参数两次外?

我怀疑没有,但可以使用更有经验的ODBC程序员的观点。

编辑 :我正在使用的ODBC驱动程序是BBj ODBC驱动程序。

在MSDN中,明确声明您不能命名参数,这是“告诉ODBC命令哪个参数是哪个”的唯一方法。

虽然文档可能会产生一些混乱:

来自MSDN,OdbcParameter类 :

当CommandType设置为Text时,.NET Framework数据提供程序for ODBC不支持将命名参数传递给SQL语句或OdbcCommand调用的存储过程。 在其中任何一种情况下,请使用问号(?)占位符。

OdbcParameter对象添加到OdbcParameterCollection的顺序必须直接对应于命令文本中参数的问号占位符的位置。

从上面看来,似乎建议当CommandType没有设置为Text时,你可以使用命名参数,但不幸的是你不能:

从MSDN,OdbcCommand.CommandType属性 :

当CommandType属性设置为StoredProcedure时,应将CommandText属性设置为完整的ODBC调用语法。 然后,当您调用其中一个Execute方法(例如,ExecuteReader或ExecuteNonQuery)时,该命令将执行此存储过程。

用于ODBC的.NET Framework数据提供程序不支持将命名参数传递给SQL语句或OdbcCommand调用的存储过程。 在任何一种情况下,使用问号(?)占位符……

谢谢汤姆的想法和你的代码。
但是,在我的测试中,代码无法正常工作。
所以我写了一个更简单的(至少在我的测试工作中)解决方案,用位置参数替换命名参数(使用?而不是名称):

 public static class OdbcCommandExtensions { public static void ConvertNamedParametersToPositionalParameters(this OdbcCommand command) { //1. Find all occurrences parameters references in the SQL statement (such as @MyParameter). //2. Find the corresponding parameter in the command's parameters list. //3. Add the found parameter to the newParameters list and replace the parameter reference in the SQL with a question mark (?). //4. Replace the command's parameters list with the newParameters list. var newParameters = new List(); command.CommandText = Regex.Replace(command.CommandText, "(@\\w*)", match => { var parameter = command.Parameters.OfType().FirstOrDefault(a => a.ParameterName == match.Groups[1].Value); if (parameter != null) { var parameterIndex = newParameters.Count; var newParameter = command.CreateParameter(); newParameter.OdbcType = parameter.OdbcType; newParameter.ParameterName = "@parameter" + parameterIndex.ToString(); newParameter.Value = parameter.Value; newParameters.Add(newParameter); } return "?"; }); command.Parameters.Clear(); command.Parameters.AddRange(newParameters.ToArray()); } } 

我无法使用命名参数 – 只有位置参数。 您可以在下面添加所需的所有参数,但必须按顺序添加值。

 SELECT * FROM myTable WHERE myField = ? or myField1 = ? or myField2 = ? or myField2 = ? myOdbcCommand.Parameters.AddWithValue("DoesNotMatter", val1); //myField myOdbcCommand.Parameters.AddWithValue("WhatYouPutHere", val2); //myField1 myOdbcCommand.Parameters.AddWithValue("DoesNotMatter", val3); //myField2 myOdbcCommand.Parameters.AddWithValue("WhatYouPutHere", val4); //myField2 

从上面可以看出,参数名称无关紧要,不使用。 如果你想要或者更好,你甚至可以将它们命名为all,将param名称留空""

我知道在使用Oracle Rdb ODBC时,我不能使用占位符名称而必须使用’?’; 我觉得非常讨厌。

我需要编写代码来处理使用问号将命名参数转换为序数参数。 我需要的是OleDb而不是Odbc …但我相信如果你改变类型,这对你有用。

 using System; using System.Collections.Generic; using System.Data.OleDb; using System.Linq; using System.Text.RegularExpressions; namespace OleDbParameterFix { static class Program { [STAThread] static void Main() { string connectionString = @"provider=vfpoledb;data source=data\northwind.dbc"; using (var connection = new OleDbConnection(connectionString)) using (var command = connection.CreateCommand()) { command.CommandText = "select count(*) from orders where orderdate=@date or requireddate=@date or shippeddate=@date"; command.Parameters.Add("date", new DateTime(1996, 7, 11)); connection.Open(); OleDbParameterRewritter.Rewrite(command); var count = command.ExecuteScalar(); connection.Close(); } } } public class OleDbParameterRewritter { public static void Rewrite(OleDbCommand command) { HandleMultipleParameterReferences(command); ReplaceParameterNamesWithQuestionMark(command); } private static void HandleMultipleParameterReferences(OleDbCommand command) { var parameterMatches = command.Parameters .Cast() .Select(x => Regex.Matches(command.CommandText, "@" + x.ParameterName)) .ToList(); // Check to see if any of the parameters are listed multiple times in the command text. if (parameterMatches.Any(x => x.Count > 1)) { var newParameters = new List(); // order by descending to make the parameter name replacing easy var matches = parameterMatches.SelectMany(x => x.Cast()) .OrderByDescending(x => x.Index); foreach (Match match in matches) { // Substring removed the @ prefix. var parameterName = match.Value.Substring(1); // Add index to the name to make the parameter name unique. var newParameterName = parameterName + "_" + match.Index; var newParameter = (OleDbParameter)((ICloneable)command.Parameters[parameterName]).Clone(); newParameter.ParameterName = newParameterName; newParameters.Add(newParameter); // Replace the old parameter name with the new parameter name. command.CommandText = command.CommandText.Substring(0, match.Index) + "@" + newParameterName + command.CommandText.Substring(match.Index + match.Length); } // The parameters were added to the list in the reverse order to make parameter name replacing easy. newParameters.Reverse(); command.Parameters.Clear(); newParameters.ForEach(x => command.Parameters.Add(x)); } } private static void ReplaceParameterNamesWithQuestionMark(OleDbCommand command) { for (int index = command.Parameters.Count - 1; index >= 0; index--) { var p = command.Parameters[index]; command.CommandText = command.CommandText.Replace("@" + p.ParameterName, "?"); } } } } 

以下是该post的简短解决方案: https : //stackoverflow.com/a/21925683/2935383

我已经为OpenEdge(Progress)ODBC包装器编写了这段代码。 DatabaseAdapter类是这个包装器,不会在这里显示。

 string _convertSql( string queryString, List parameters, ref List odbcParameters ) { List sorter = new List(); foreach (DatabaseAdapter.Parameters item in parameters) { string parameterName = item.ParameterName; int indexSpace = queryString.IndexOf(paramName + " "); // 0 int indexComma = queryString.IndexOf(paramName + ","); // 1 if (indexSpace > -1){ sorter.Add(new ParamSorter() { p = item, index = indexSpace, type = 0 }); } else { sorter.Add(new ParamSorter() { p = item, index = indexComma, type = 1 }); } } odbcParameters = new List(); foreach (ParamSorter item in sorter.OrderBy(x => x.index)) { if (item.type == 0) { //SPACE queryString = queryString.Replace(item.p.ParameterName + " ", "? "); } else { //COMMA queryString = queryString.Replace(item.p.ParameterName + ",", "?,"); } odbcParameters.Add( new System.Data.Odbc.OdbcParameter(item.p.ParameterName, item.p.Value)); } } 

排序的实用程序类

 class ParamSorter{ public DatabaseAdapter.Parameters p; public int index; public int type; } 

如果命名参数是字符串中的最后一个 – 您必须添加一个空格。 例如"SELECT * FROM tab WHERE col = @mycol"必须"SELECT * FROM tab WHERE col = @mycol "