如何确定哪一行导致错误 - 错误检查

时间:2013-02-21 23:36:32

标签: sql-server sql-server-2005 sql-server-2000 runtime-error

我看到另一张海报(WolfiG)提出了一个非常相似的问题,但我没有看到答案。 (我理解错误消息,并不是在寻找如何修复错误,我正在尝试确定是否有任何类型的错误检查(或调试技术)用于其他错误。

我找到了类似的代码并添加到它中,以获取服务器上每个数据库中的每个表...并显示PK和行计数。 (处理库存,然后处理数据字典 - 但这不是问题,我只是解释代码是如何形成的。)

所以在这种情况下,我已经稍微缩小了数据范围(这意味着我知道我正在查询哪个数据库并遇到错误)所以“只有”81个表(行)可能出错了。但是当然需要过多的手动检查来找到问题,所以我希望有一种方法可以看到当子查询得到错误时正在读取哪个“t.name”。 (我通过一次评论一行来缩小第一个子查询的范围(有10个,我只是没有在这里复制所有这些。)

问题再次出现(看起来我不是唯一一个提出此类问题的人) - 有没有办法确定哪一行(数据)导致查询出错?

并在下面的示例中,     当发生错误时,有没有办法显示t.name(或其他列的数据)是最近的?

在Mainframe中工作 - 您可以查看转储或缓冲区。但我想我不想期待太多,因为我一直看到神秘的消息,显然系统有信息但不显示它。

Msg 512,Level 16,State 1,Line 1 子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

use [DBName]
SELECT '[DBName]' as DBName, t.NAME, it.xtype,i.rowcnt, 
   (select c.name from syscolumns c inner join sysindexkeys k on k.indid=i.indid and c.colid = k.colid and c.id=t.id and k.keyno=1 and k.id=t.id)as 'column1',
   (select c.name from syscolumns c inner join sysindexkeys k on k.indid=i.indid and c.colid = k.colid and c.id=t.id and k.keyno=2 and k.id=t.id)as 'column2'  
  from sysobjects t inner join sysindexes i on i.id=t.id   
    LEFT OUTER JOIN   sysobjects it on it.parent_obj=t.id and it.name = i.name
 WHERE  i.indid < 2 AND OBJECTPROPERTY(t.ID, 'IsMSShipped') = 0 

谢谢!

顺便说一下,我是如何找到导致此错误的行(如果这会对其他人有帮助)是我将第一个子查询更改为“select count(c.name)来自syscolumns“然后查找数字为&gt;的所有行1.

塞巴斯蒂安·梅恩谢谢你,但现在我遇到了另一个问题。 (我不得不说,我非常遗憾地质疑你的评论,SQL比字典的其他数据库更好.GRRRR)

我正在使用“i.indid&lt; 2”,因为 - 首先,我试图获得rowcnt,老实说样本都使用它。但是我看到你粘贴的查询如何得到更多的行而原来错过 - 显然是因为检查:i.indid&lt; 2

然而,有了你的查询,我现在得到了更多同一张桌子的出现,我无法看到在我打字的时候“总结”/ ARGHHH 怎么可能我看到了COLS不仅是主键,而且显示了相同的表名(并且具有不同的行数,在许多情况下,表中的每一列都有一行 - 而在其他情况下则不行)。所以寻找一个模式,我发现MAYBE sysindexes.status =可能会限制我的结果 - 但是当它接近时仍然存在重复的行。再次ARGGGH

2 个答案:

答案 0 :(得分:3)

SQL Server不提供逐行调试的功能。一切都作为一套处理。如果一个元素不符合规则,则整个查询失败。

因此,要查找有问题的行,您需要编写单独的查询,就像您已经做过的那样。

SQL 2000中的目录竞争并不是很好,但是由于已经大大改进并提供了比大多数其他RDBMS更多的细节。但是,由于您似乎需要编写一个运行在所有查询上的查询,请尝试以下方法:

 SELECT DB_ID() AS DBName,
        o.name,
        i.rowcnt,
        i.keycnt,
        cols.column1,
        cols.column2,
        cols.column3,
        cols.column4
 FROM   sysobjects o
 JOIN   sysindexes i
        ON o.id = i.id
 JOIN   (
          SELECT  k.id,
                  k.indid,
                  MAX(CASE WHEN k.keyno = 1 THEN c.name END) AS column1,
                  MAX(CASE WHEN k.keyno = 2 THEN c.name END) AS column2,
                  MAX(CASE WHEN k.keyno = 3 THEN c.name END) AS column3,
                  MAX(CASE WHEN k.keyno = 4 THEN c.name END) AS column4
          FROM    sysindexkeys k
          JOIN    syscolumns c
                  ON k.id = c.id
                  AND k.colid = c.colid
          GROUP BY k.id, k.indid
        ) cols
        ON i.id = cols.id
        AND i.indid = cols.indid

我没有运行SQL 2000版本试试这个,但我相信它会运行。

要注意两件事:

  1. SQL 2000中的sysindexes.rowcnt值非常不可靠。您在以后版本的sys.indexes中找到的值是可靠的,但不符合ACID。

  2. 索引中最多可以有16个列。我在查询中添加了4,并添加了keycnt列,因此您知道丢失了多少。

答案 1 :(得分:1)

我觉得有用的是重新构造sql以便更容易出错。除非绝对需要,否则我会避免一般的子查询。

否则,如果您使用子查询,则还需要考虑它们在标量上下文中返回多个结果的情况。

通常,像这样的大多数子查询都可以重写为连接。然后,您还可以直接查看重复的数据 - 您可以在重复的字段上将表连接到自身,以使id不相等。