5

別の投稿者 (WolfiG) が非常によく似た質問をしているのを見ましたが、答えがわかりません。(私はエラー メッセージを理解していますが、エラーを修正する方法を探しているわけではありません。他のエラーに使用するエラー チェック (またはデバッグ手法) の種類があるかどうかを判断しようとしています。

サーバー上の各データベースの各テーブルを取得し、PK と行数を表示するために、同様のコードを見つけて追加しました。(インベントリとデータ ディクショナリに取り組んでいますが、これは問題ではありません。コードがどのようになったかを説明しているだけです。)

SO この場合、私はすでにデータをいくらか絞り込んでいました (つまり、どのデータベースをクエリしてエラーが発生したかを知っているということです)。ただし、もちろん、問題を見つけるには手動でチェックする必要がありすぎるため、サブクエリでエラーが発生したときにどの「t.name」が読み取られているかを確認する方法があることを望んでいました。(一度に 1 行ずつコメントアウトして、最初のサブクエリを絞り込みました (10 行あり、ここではすべてをコピーしませんでした。)

繰り返しになりますが、質問は (この種の質問をするのは私だけではないようです) - クエリでエラーが発生した行 (データ) を特定する方法はありますか?

以下の例で は、エラーが発生したときに t.name (または他の列のデータ) が最新であったことを表示する方法はありますか?

メインフレームで作業した後、ダンプまたはバッファを確認できます。しかし、システムには明らかに情報があるのに表示されない不可解なメッセージが表示され続けるので、あまり期待したくないと思います。

メッセージ 512、レベル 16、状態 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 は辞書の他の DB よりも優れているというあなたのコメントに、私はかなり悲しいことに異議を唱えていると言わざるを得ませんでした。GRRRR)

「i.indid < 2」を使用していたのは、最初は最初にrowcntを取得しようとしていて、正直なところすべてのサンプルがそれを使用していたからです。しかし、貼り付けたクエリがはるかに多くの行を取得し、元のクエリが欠落していることがわかります-明らかにチェックが原因です: i.indid < 2

ただし、クエリを使用すると、同じテーブルがさらに多く発生するようになり、これを入力しているときに /ARGHHH を「要約」する方法がわかり ません。 COLS は主キーだけでなく、同じテーブル名が表示されます(行数が異なり、多くの場合、テーブルのすべての列に行があったように見えますが、他の場合はそうではありません)。したがって、パターンを探していると、MAYBE sysindexes.status = が結果を制限する可能性があることがわかりましたが、それが近いうちに、まだ重複した行がありました。再びARGGGH

4

2 に答える 2

3

SQL Server には、行ごとのデバッグを行う機能はありません。全てセット扱いとなります。1 つの要素がルールに準拠していない場合、クエリ全体が失敗します。

したがって、問題のある行を見つけるには、既に行ったように別のクエリを作成する必要があります。

SQL 2000 のカタログ ビューはそれほど優れたものではありませんでしたが、その後大幅に改善され、他のほとんどの RDBMS よりも多くの詳細を提供します。しかし、すべてで実行される 1 つのクエリを作成する必要があるように思われるので、次のようにしてみてください。

 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 バージョンはもう実行していませんが、実行されると思います。

次の 2 つの点に注意してください。

  1. sysindexes.rowcnt 値は、SQL 2000 では非常に信頼できませんでした。それ以降のバージョンの sys.indexes にある値は信頼できますが、ACID に準拠していません。

  2. インデックスには最大 16 個の列を含めることができます。クエリに 4 を追加し、keycnt 列も追加したので、欠落している数がわかります。

于 2013-02-22T02:35:47.370 に答える
1

私が役立つと思うのは、SQLを再構築して、トラブルシューティングを容易にすることです。どうしても必要な場合を除いて、一般的にサブクエリは避けます。

それ以外の場合、サブクエリを使用する場合は、サブクエリがスカラーコンテキストで複数の結果を返す場合も考慮する必要があります。

通常、このようなほとんどのサブクエリは、結合として書き直すことができます。次に、どのデータが複製されているかを直接確認することもできます。IDが等しくないように、複製されたフィールドでテーブルをそれ自体に結合できます。

于 2013-02-22T00:09:35.600 に答える