如何避免使用重复列的订单上的SQL Server错误



尽管此问题引用了PHP,但实际上不是PHP特定的,因此我没有这样标记。

我们有一个支持多个DB后端的PHP框架。

我们的数据对象类中有一个通用功能,它允许您使用指定的标准和排序订单从基础表获得记录。

看起来像这样:

function GetAll($Criteria, $OrderBy = "") {
    ...
    // Add primary key (column 1) to end of order by list,
    // so that returned order is predictable.
    if ($OrderBy != "") {
        $OrderBy .= ", ";
    }
    $OrderBy .= "1";
    ...
    // Build and run query, returning the result as an array.
}

如果您在Staff对象上指定StaffID$OrderBy参数,则结果SQL看起来如下:

SELECT * FROM adminStaff ORDER BY StaffID, 1;

这在MySQL后端上正常工作,从我对网络的搜索中,在大多数其他DB后端也应该很好。但是,使用SQL Server时,我们会收到以下错误消息:

A column has been specified more than once in the order by list.
Columns in the order by list must be unique.

这是因为SQL Server将同一列在订单中通过子句多次出现。在这种情况下,StaffID是第1列,因此我们有同一列的多个实例。

有没有办法在SQL Server中禁用此检查?MySQL提供了许多选项来启用/禁用严格检查和不兼容的功能 - SQL Server是否提供了允许上述查询无错误运行的任何性质?

如果没有,您对如何在数据对象层中解决此问题有任何建议吗?请记住,我们需要与期望这种行为的现有项目保持兼容性,因此仅在$OrderBy为空白时仅包含第一列就不足

这种情况也有些复杂,因为该字段列表在数据对象配置中的其他位置可以自定义,因此我们不能依靠*用作字段列表 - 它可以包含几乎所有有效的内容普通的SQL字段列表。但是,如果要问太多,那么对简单情况的解决方案(如上所述)将是一个不错的开始!

在SQL Server中能够按列名或选择列表中的列顺序排序。

在您的情况下,StaffID列成为序列位置1。因此,SQL Server不能两次基于同一列的相同结果集。

如果您从查询中删除1,则将解决问题。

避免使用列的顺序位置进行排序。

基本问题 - 是否可以按列抑制此SQL Server限制此SQL Server限制重复 - 由Venu回答:不。

关于如何以通用方式围绕此限制进行编码的各种建议(主要来自我)。对于任何未来的读者来说,如果您适应现有系统,这些答案可能最有用。(如果您是从头开始的,请尝试完全避免这种情况。)

但是,我提出的实际解决方案是为我们的DBAL添加内部API版本。API版本现在为2,但您可以致电setApiVersion(1)指示使用API的旧版本的后端。

v2与v1*相同,除非它不再自动将列1添加到订单中,除非它完全空白。因此,对于新的(V2)项目解决了SQL Server问题,而现有项目可以设置为使用V1 API并因此继续正确工作(但没有SQL Server兼容性)。

(*实际上,我借此机会在V2中进行了其他一些破裂的更改,但这与此答案无关。)

我在框架级别提出了一些潜在的解决方案。所有这些都有需要对其进行介绍的绩效含义,而实际上,可能会将其中的一些或全部统治。但是,至少从理论上讲,这些是可以实施通用解决方案的方式。

  1. 通过完全省略订单,然后在代码中进行排序。将涉及通过字符串解析提供的订单。如果按包含的表达式顺序排序,那将是有问题的,但是我不记得在我们的项目中看到过,因此可能会被忽略。可能是最慢的解决方案。
  2. 执行无订单的查询,将结果设置为单行。使用结果列列表来确定第1列是否已经按子句按顺序列出来,因此是否添加它。然后运行完整的查询。将需要按字符串解析提供的订单。查询缓存 May 意味着这不会添加到看起来那么多的开销。
  3. 解析字段列表以获取第一个列名,并查看是否以子句为单词出现。如果字段列表包含*table.*,则需要查找架构。如果我们需要结合使用桌子别名和通配符,可能太困难了。
  4. 通过字符串解析订单,看看它是否包含任何主键。如果是这样,它已经是唯一的订购,并且不需要添加额外的字段。将需要架构查找。
  5. 使用子选项为我们提供可以对其进行排序的列的新实例。不确定SQL Server是否仍然会抱怨这是"同一"列。

在使用SQL Server时,您可以将' ->

最新更新