5

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

我找到了类似的代码并将其添加到其中,以获取服务器上每个数据库中的每个表......并显示 PK 和行数。(处理清单,然后处理数据字典——但这不是问题,我只是在解释代码是如何产生的。)

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

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

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

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

消息 512,级别 16,状态 1,第 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 

谢谢!

顺便说一句,我如何能够找到导致此错误的行(以防这对其他人有帮助)是我将第一个子查询更改为“从 syscolumns 中选择count(c.name) ”,然后查找任何数字大于 1 的行。

Sebastian Meine 谢谢,但现在我遇到了另一个问题。(我不得不说,我非常遗憾地反驳你的评论,即 SQL 比字典中的其他数据库更好。GRRRR)

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

但是,通过您的查询,我现在在同一个表中出现了更多的情况,并且我看不到在我输入这个时如何“总结”/ARGHHH 我看到 COLS 不仅是主键,而且显示相同的表名(并且具有不同的行数,并且看起来在许多情况下,表中的每一列都有一行 - 而在其他情况下则没有)。因此,在寻找一种模式时,我发现 MAYBE sysindexes.status = 可能会限制我的结果 - 但是虽然很接近,但仍然有重复的行。再次ARGGGH

4

2 回答 2

3

SQL Server does not provide the ability to do row by row debugging. Everything is handled as a set. If one element does not conform to the rules the whole query fails.

So, to find the offending row you need to write a separate query, as you already did.

The catalog vies in SQL 2000 have not been that great but since have been greatly improved and provide a lot more detail than most other RDBMSs out there. But since you seem to have the requirement to write one query that runs on all, try this:

 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

I do not have a SQL 2000 version running anymore to try this on, but I believe it will run.

Two things to be aware of:

  1. The sysindexes.rowcnt value was very unreliable in SQL 2000. The value you find in sys.indexes in later versions is reliable but not ACID compliant.

  2. There can be up to 16 kolumns in an index. I added 4 to the query and also added the keycnt column, so you know how many you are missing.

于 2013-02-22T02:35:47.370 回答
1

我发现有用的是重新构建 sql 以使其更容易排除故障。除非绝对需要,否则我一般会避免子查询。

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

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

于 2013-02-22T00:09:35.600 回答