3

前提

select我最近在我的代码中的一个语句中遇到了一个错误。在我意识到发生了什么之后修复它是相当微不足道的,但我有兴趣找到一种方法来确保类似的错误不会再次发生。

这是一个违规查询的示例:

select
  the,
  quick,
  brown
  fox,
  jumped,
  over,
  the,
  lazy,
  dog
from table_name;

我的本意是:

select
  the,
  quick,
  brown,
  fox,
  jumped,
  over,
  the,
  lazy,
  dog
from table_name;

对于那些没有看到它的人,brown前者后面缺少逗号。这会导致列被别名,因为as关键字不是必需的。所以,你得到的结果是:

  the,
  quick,
  fox,
  jumped,
  over,
  the,
  lazy,
  dog

...brown在名为 的列中包含所有值fox。对于像上面这样的短查询(尤其是当每列具有非常不同的值时)很容易注意到这一点,但是它出现在一个相当复杂的查询中,其中大部分是整数列,如下所示:

select
  foo,
  bar,
  baz,
  another_table.quux,
  a1,
  a2,
  a3,
  a4,
  a5,
  a6,
  a7,
  a8,
  a9,
  a10,
  a11,
  a12,
  a13,
  a14,
  a15,
  a16,
  b1,
  b2,
  b3,
  b7,
  b8,
  b9,
  b10,
  b11,
  b12,
  b13,
  b14,
  b18,
  b19,
  b20,
  b21,
  c1,
  c2,
  c3,
  c4,
  c5,
  c6,
  c7,
  c8
from table_name
join another_table on table_name.foo_id = another_table.id
where
  blah = 'blargh'
-- many other things here
;

即使使用更好的列名,这些值也非常相似。b11如果我在(例如)之后错过了一个逗号,然后所有的b11值都被调用了b12,那么当我们通过处理管道运行数据时(这取决于结果中的这些列名),这是非常不幸的。通常情况下,我会这样做select * from table_name,但我们需要的是比这更有选择性。

问题

我正在寻找的是一种阻止这种情况再次发生的策略。

别名列时有没有办法要求as?或者写东西让它出错的技巧?(例如,在类 C 语言中,当我不小心遗漏了一个等号时,我开始编写1 == foo而不是导致编译错误,使其无效而不是。)foo == 11 = foofoo = 1

vim正常使用,所以我可以用它hlsearch来突出逗号,这样我就可以看到它了。但是,我必须经常在其他环境中编写查询,包括在其中我无法轻松执行此类操作的专有接口。

谢谢你的帮助!

4

5 回答 5

6

我之前做过的一件事是将逗号移到行首。这带来了一些好处。首先,您可以立即查看是否缺少任何逗号。其次,您可以在末尾添加一个新列,而无需修改之前的最后一行。

失踪:

select
  the
, quick
, brown
  fox
, jumped
, over
, the
, lazy
, dog
from table_name;

不缺:

select
  the
, quick
, brown
, fox
, jumped
, over
, the
, lazy
, dog
from table_name;
于 2009-11-19T16:51:56.797 回答
1

您可以将 SQL 调用包装在一个函数中,该函数可以:

  1. 遍历结果集中的列,检查包含空格的列名

或者

  1. 接受 SQL 语句和预期的整数列数,然后检查结果集以确保列数与您的预期相符。
于 2009-11-19T16:53:53.220 回答
1

我和你有同样的问题。我已经使用 make 和 perl 脚本来做一个“lint”,比如检查我的代码很长一段时间。它有助于防止一些类似的错误。在makefile中我有:

lint_code:
    perl lint_code.pl <file_1.php

perl 文件是:

$st = 0;
$line_no = 0;
while (<>)
{
   $line_no++;
   $st = 1 if ( /start-sql/ );
   $st = 0 if ( /end-sql/ );
   $st = 2 if ( $st == 1 && /select/ );
   $st = 3 if ( $st == 2 && /from/ );
   if ( $st == 2 && /^[ \t]+[a-zA-Z][a-zA-Z0-9]*[ \t*]$/ )
   {
      if ( ! /select/ )
      {
         printf ( "Possible Error: Line: $line_no\n" );
      }
   }
}

我用注释//start-sql 和//end-sql 包围我的选择语句。我希望这有帮助。我已经更改了正则表达式以反映您如何格式化 SQL,因为我一直在使用不同的格式(前面有逗号)。

作为构建/测试过程的一部分,我对代码进行了一系列检查。这是一个不太完美的解决方案,但它帮助了我。

(我在使用 stackoverflow 富文本编辑器更改我的代码时遇到了一点困难。希望我能学会如何正确使用它。)

于 2009-11-19T17:03:26.323 回答
0

在名字前写一个逗号

first
,short
,medium
,longlonglong
,...

对比

first,
short,
medium,
longlonglong,
...

还可以很容易地查看 sql 选择参数列表

适用于任何 IDE :)

于 2009-11-19T16:50:14.507 回答
-1

如果您有名称相似的列,仅以后缀数字区分,那么您已经迷路了。你有一个糟糕的数据库设计。

现在大多数现代开发人员都使用 SQL 生成器或 ORM,而不是编写这种“汇编语言”SQL。

于 2009-11-19T16:51:09.543 回答