English 中文(简体)
SQLite column aliasing
原标题:
  • 时间:2009-11-19 16:46:30
  •  标签:
  • sql
  • alias

Premise

I recently ran into a bug in a select statement in my code. It was fairly trivial to fix after I realized what was going on, but I m interested in finding a way to make sure a similar bug doesn t happen again.

Here s an example of an offending query:

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

What I had intended was:

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

For those who don t see it, a comma is missing after brown in the former. This causes the column to be aliased, because the as keyword is not required. So, what you get in the result is:

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

...with all the values of brown in a column named fox. This can be noticed pretty easily for a short query like the above (especially when each column has very different values), but where it came up was in a fairly complicated query with mostly integer columns like this:

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
;

Even with better column names, the values are all very similar. If I were to miss a comma after b11 (for example) and then all of the b11 values get called b12, it s pretty unfortunate when we run the data through our processing pipeline (which depends on these column names in the result). Normally, I d do select * from table_name, but what we needed required us to be a little more selective than that.

Question

What I m looking for is a strategy to stop this from happening again.

Is there a way to require as when aliasing columns? Or a trick of writing things to make it give an error? (For example, in C-like languages, I started writing 1 == foo instead of foo == 1 to cause a compile error when I accidentally left out an equal sign, making it the invalid 1 = foo instead of foo = 1.)

I use vim normally, so I can use hlsearch to highlight commas just so I can eyeball it. However, I have to write queries in other environments quite often, including a proprietary interface in which I can t do something like this easily.

Thanks for your help!

最佳回答

One thing that I ve done before is to move the commas to the beginning of the line. This allows some benefits. First, you can instantly see if there are any commas missing. Second, you can add a new column at the end without having to modify the previously last line.

Missing:

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

Not missing:

select
  the
, quick
, brown
, fox
, jumped
, over
, the
, lazy
, dog
from table_name;
问题回答

You could wrap your SQL calls in a function that would either:

  1. Iterate over the columns in the result set, checking for column names containing a space

or

  1. Accept both the SQL statement and an integer intended number of columns, then check the result set to make sure the number of columns matches what you intended.

I have the same problem that you do. I have used make and the perl script to do a "lint" like check on my code for a long time. It has helped prevent a number of mistakes like this. In the makefile I have:

lint_code:
    perl lint_code.pl <file_1.php

The perl file is:

$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 && /^[ 	]+[a-zA-Z][a-zA-Z0-9]*[ 	*]$/ )
   {
      if ( ! /select/ )
      {
         printf ( "Possible Error: Line: $line_no
" );
      }
   }
}

I surround my select statements with comments //start-sql and //end-sql. I hope this helps. I have changed the regular expression to reflect how you formatted your SQL as I have been using a different format (with the commas in the front).

As a part of my build/test process I run a set of checks over the code. This is a less than perfect solution but it has helped me.

(I am having a little difficulty with the stackoverflow rich text editor changing my code. Hopefully I will learn how to properly use it.)

write a comma before the name

first
,short
,medium
,longlonglong
,...

vs

first,
short,
medium,
longlonglong,
...

also makes it really easy to see the list of sql select arguments

works in any IDE :)

If you have columns with similar names, distinguished only by suffix numbers, you ve already lost. You have a bad database design.

And most modern developers use SQL generators or ORMs these days, instead of writing this "assembly language" SQL.





相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签