测试SQL查询的最佳方式

所以我遇到了一个问题,我们保持复杂的SQL查询出错,错误。

本质上这导致发送邮件给不正确的客户和其他类似的问题。

每个人创建这样的SQL查询的经验是什么,基本上我们每隔一周创建一个新的数据组。

所以这里有一些我的想法和他们的限制。

创建测试数据 – 虽然这将证明我们有所有正确的数据,但并不强制排除生产中的异常。这是今天被认为是错误的数据,但可能在10年前是正确的,它没有记录,因此我们只有在数据提取后才知道。

创建维恩图和数据映射 – 这似乎是测试查询设计的一个坚实的方法,但它不保证实现是正确的。它让开发人员向前平移,思考他们写的时候发生了什么。

感谢您的任何输入,你可以给我的问题。

你不会写一个200行长的应用程序。你将这些长函数分解为更小的函数,每个函数都有一个明确定义的责任。

为什么要这样写你的SQL?

分解你的查询,就像分解你的函数。这使他们更短,更简单,更容易理解,更容易测试,更容易重构。它允许您在它们之间添加“垫片”,并在它们周围添加“包装器”,就像在过程代码中一样。

你怎么做到这一点?通过使查询中的每个重要事物进入视图。然后,你从这些更简单的视图中编写更复杂的查询,就像你从更原始的函数中组成更复杂的函数一样。

最棒的是,对于大多数视图组合,您将获得与RDBMS完全相同的性能。 (对于某些你不会;所以什么?过早的优化是所有邪恶的根源。代码正确的第一,然后优化,如果你需要)。

Here’s an example of using several view to decompose a complicated query.

在示例中,因为每个视图只添加一个转换,每个视图可以独立测试以查找错误,测试很简单。

下面是示例中的基表:

create table month_value( 
    eid int not null, m int, y int,  v int );

此表有缺陷,因为它使用两列,月和年来表示一个基准,绝对月。以下是新的计算列的规格:

We’ll do that as a linear transform, such that it sorts the same as (y, m), and such that for any (y,m) tuple there is one and only value, and all values are consecutive:

create view cm_abs_month as 
select *, y * 12 + m as am from month_value;

现在我们要测试的是我们的规范中固有的,即对于任何元组(y,m),只有一个(am),并且(am)是连续的。让我们写一些测试。

我们的测试将是一个SQL选择查询,具有以下结构:测试名称和案例语句结合在一起。测试名称只是一个任意字符串。 case语句只是当测试语句然后“传递”else’false’结束的情况。

测试语句将只是SQL选择(子查询),测试必须为true才能通过。

这是我们的第一个测试:

--a select statement that catenates the test name and the case statement
select concat( 
-- the test name
'For every (y,m) there is one and only one (am): ', 
-- the case statement
   case when 
-- one or more subqueries
-- in this case, an expected value and an actual value 
-- that must be equal for the test to pass
  ( select count(distinct y, m) from month_value) 
  --expected value,
  = ( select count(distinct am) from cm_abs_month)  
  -- actual value
  -- the then and else branches of the case statement
  then 'passed' else 'failed' end
  -- close the concat function and terminate the query 
  ); 
  -- test result.

运行该查询产生这个结果:对于每个(y,m),只有一个(am):传递

只要在month_value中有足够的测试数据,此测试工作。

我们还可以为足够的测试数据添加测试:

select concat( 'Sufficient and sufficiently varied month_value test data: ',
   case when 
      ( select count(distinct y, m) from month_value) > 10
  and ( select count(distinct y) from month_value) > 3
  and ... more tests 
  then 'passed' else 'failed' end );

现在让我们测试它是连续的:

select concat( '(am)s are consecutive: ',
case when ( select count(*) from cm_abs_month a join cm_abs_month b 
on (( a.m + 1 = b.m and a.y = b.y) or (a.m = 12 and b.m = 1 and a.y + 1 = b.y) )  
where a.am + 1 <> b.am ) = 0 
then 'passed' else 'failed' end );

现在让我们把我们的测试,只是查询,放入一个文件,并对数据库运行该脚本。事实上,如果我们将视图定义存储在脚本(或脚本,我建议每个相关视图一个文件)以针对数据库运行,我们可以将每个视图的测试添加到同一个脚本,因此, – )创建我们的视图也运行视图的测试。这样,当我们重新创建视图时,我们都获得了回归测试,当视图创建对生产运行时,视图也将在生产环境中进行测试。

http://stackoverflow.com/questions/754527/best-way-to-test-sql-queries

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:测试SQL查询的最佳方式