SQL文が化ける原因と対策を教えてください

このQ&Aのポイント
  • VB6.0でADOを使用してSQLServer2005に接続しています。あるSELECT文を取得条件だけ変更して連続して発行し、結果を変数に取り込むプログラムで、なぜか4000~5000件ごとにSQLがタイムアウトしてしまいます。
  • プロファイラで確認したところ、VB側で発行したSELECT文の頭になぜか「select * from」がくっついたSQL文が表示されます。前後のSQL文は正しく動いており、SQL文が間違っているように思えません。
  • このような現象は、連続して発行するSQLの件数が少ないときは発生しませんでした。原因がわからず、修正もできず困っています。アドバイスよろしくお願いいたします。
回答を見る
  • ベストアンサー

SQL文が化ける(select * from が頭にくっつく)原因と対策を教えてください

VB6.0でADOを使用してSQLServer2005に接続しています。 あるSELECT文を取得条件だけ変更して連続して発行し、結果を変数に取り込むプログラムで、なぜか4000~5000件ごとにSQLがタイムアウトしてしまいます。   プロファイラで確認したところ、VB側で発行したSELECT文の頭になぜか「select * from」がくっついたSQL文が表示されます。   前後のSQL文は正しく動いており、SQL文が間違っているように思えません。 このような現象は、連続して発行するSQLの件数が少ないときは発生しませんでした。 【SQLの例】 VB側の送信 SELECT GP.ID番号, GP.KURA番号, GP.CR番号, GP.CRKYOKA, CR.READERNo FROM 区分 GP LEFT JOIN リーダ名 CR ON (GP.KURA番号 = CR.KURA番号 AND GP.CR番号 = CR.CR番号) WHERE ID番号 ='00AZ6535' SQLServer側(プロファイラ) select * from SELECT GP.ID番号, GP.KURA番号, GP.CR番号, GP.CRKYOKA, CR.READERNo FROM 区分 GP LEFT JOIN リーダ名 CR ON (GP.KURA番号 = CR.KURA番号 AND GP.CR番号 = CR.CR番号) WHERE ID番号 ='00AZ6535' 原因がわからず、修正もできず困っています。 アドバイスよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

これはODBCですね。 再現すれば苦労はないのですが、同じ構造で何万回コールしても再現させられませんでした(XP SP3 & SQL Server 2005)。 再現させられない以上、私としては代替案をお勧めするしかないのですが、 ・プロバイダを変更してみる  a) psAConnect = "Provider=SQLOLEDB;Data Source=(サーバー);Initial Catalog=(データベース);User ID=(ユーザ);Password=(パスワード);"  b) psAConnect = "Provider=SQLNCLI;Data Source=(サーバー);Initial Catalog=(データベース);User ID=(ユーザ);Password=(パスワード);" ・1万回以上もSQL文を投げる構造を改める  この書き方をしている以上はキー項目はローカルにあるのでしょうが、そこまでヒット率が低いなら全部取ってきてローカルで調べた方がいいと思います。  (もしくはIN句で100~1000件単位でまとめて検索するか)  今の方法だとすべてのSQL文が別物とみなされてキャッシュが殆ど使われないので、さらに遅いと思いますしね。

askWaka
質問者

お礼

ありがとうございます。 私が試験をしたときも、サーバーを変えると再現しない場合がありました。 SQLServer2005試用版で、セットアップ時に「スペックが足りない」と警告されるようなサーバーを使用して試験したときでした。 お勧めいただいた「1万回以上もSQL文を投げる構造を改める」方法を検討してみます。 ありがとうございました。

askWaka
質問者

補足

すいません、お礼の文章がなんだか失礼に見えてしまったので、お礼の補足です。 決してjamshid6さんに試験していただいた環境が悪い、と申しているわけではありませんので、どうかそのようにお読みください。 再現試験していただき、アドバイスをいただいたこと、本当に感謝しています。 ありがとうございました。

その他の回答 (2)

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

#1です。 >お礼の文章がなんだか失礼に見えてしまったので 全然気にする必要はありません。失礼な表現でもないと思います。 回答する側としては、役に立ったか/立たなかったかさえ分かればそれで構わないですし、 仮に役に立たなくても自分のスキル維持には役立ちます(ADOは今仕事で書いていないですしね)。

askWaka
質問者

お礼

SQLを何が何でも投げる構造を見直し、必要な場合のみSQLをなげる条件をVB側で追加することで、問題の回避ができそうです。 jamshid6さんから回答をいただくことで、問題点の整理ができました。 ありがとうございました。

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

・ADOの構文も何パターンもありますが、どうやってSQLを投げているのか ・MDACのバージョンは ・使っているプロバイダは といった情報がないと再現するかどうかも確認できないですね。 SQL ServerはSQL文を受け取っている方であって、「select * from」はVB側(厳密にはADO)がつけているわけですから。 (投げたSQL文がテーブルと誤認されれば、select * fromがついてしまう可能性があるかなと思いますが。。)

askWaka
質問者

補足

ありがとうございます。補足いたします。 MDACのバージョンは2.8 SP1(WindowsXP SP3)です VB6の参照設定で、Microsoft ActiveX Data Objects 2.8 Library (msado15.dll)を参照する設定にしています。 接続時プロバイダは指定しておりませんので、ADOのデフォルトの Microsoft ODBC Provider for OLE DB と思います。 リトライ処理、エラー処理等をカットして、コードをまとめてみました。 --------- Public psAConnect As String 'ADODB接続文字列 Public pADB As ADODB.Connection 'ADOコネクション --------- If pADB Is Nothing Then Set pADB = CreateObject("ADODB.Connection") End If pADB.ConnectionTimeout = 60 pADB.CommandTimeout = 180 psAConnect = "Driver=SQL Server;Server=(サーバー);Database=(データベース);UID=(ユーザ);PWD=(パスワード);" pADB.Open psAConnect --------- Dim rsRec As ADODB.Recordset Dim sSQL As String sSQL = (質問文のSQL。WHERE ID番号 ='00AZ6535' の部分がかわります。) Set rsRec = pADB.Execute(sSQL, , adCmdText) --------- このあと、取得したレコードセットを変数に代入処理し、 rsRec.Closeし、次のID番号でのレコードセット取得にうつります。 実際のID番号件数は約17000件です。 また、実際は「区分」テーブルに10件程度しかデータがないため、このSQLで取得するレコードセットは0件の場合がほとんどです。 よろしくお願いいたします。

関連するQ&A

  • SELECT * FROM セレクト文の解釈

    SQL文について SELECT CustomerID, CompanyName FROM Customers セレクト文なのですがセレクトは その名の通り「選ぶ」という意味で fromは「から」という意味だと思うのですが select * from は「~から選んだ」みたいな解釈で良いのでしょうか? SQL初心者です。

  • SQLのSELECT文教えてください。

    VB5.0で、DBはSqlServer2000です。 SQL文のSELECT文で質問です。 ○A_TABLEの構成(概略) ・・・担当コード1・・・担当コード2 ○TANTO_TABLE 担当コード/担当名 (質問)TANTO_TABLEからA_TABLEの担当コード1と担当コード2の担当名を抽出したいのです。 次のSQLだと担当コード1のみしか抽出できません。 効率よく担当コード1と2の担当名を抽出するSQLを教えてください。お願いします。 SELECT 担当名 FROM A_TABLE,TANTO_TABLE WHERE A_TABLE.担当コード1 = TANTO_TABLE.担当コード

  • SQLのSELECT文で*を使わない理由

    SQLでSELECT文を使う場合、大抵  SELECT ID, user FROM u_table のように、取得する項目を指定すると思います。 これを、  SELECT * FROM u_table としないのには、トラフィックの問題以外に何か理由があるのでしょうか?

  • SQL文について

    開発言語:VB2010 DB:SqlServer2005 及び ACCESS2007 SQLサーバーのテーブルをAccessのテーブルへINSERTしたいのですが、 一文で行う事は可能でしょうか? (テーブルの構造は全く同じです) 同じDB内であれば、下記のような感じで出来ると思うんですが。 +----------------------------------+ INSERT into Atest_ACCESS SELECT * FROM Btest_SQL Where OperationDate => 2011/09/05 +----------------------------------+ 出来るのあればどのようにすれば良いのが教えて頂けると幸いです。 よろしくお願い致します。

  • SQLServer2000 SQL文について

    SQLServer2000 SQL文について Where句内で、このような演算指定はできますか? できない場合このようなSQLを実行したい場合 他にどのような方法が考えられますでしょうか? select a.id from a,b where a.yymm = b.yymm-1

  • SQLでSELECTの中でSELECT文を作りたいのですが。

    開発環境 VB6 WINXP  SQLで、次のそれぞれの文((1)、(2))は問題なく動作しますが、これを合体させて、絞り込むにはどうしたら良いのでしょうか。 (1) strSQLM = "SELECT * FROM 漁獲DATA WHERE 日付 =#" & Format(PickedDate, "m-d-yy") & "#" (2) strSQLM = "SELECT * FROM 漁獲DATA WHERE 順位 =" & Meigara つまり同一の日の同じ順位のデータを調べたいのですが。よろしくお願いします。

  • PHP上のSQLで、SELECT文をいくつも書くか、サブクエリやjoinを駆使して一つにまとめるか

    PHP上でSQLの、複数のテーブルを呼び出すとき、 サブクエリやjoinを駆使して、一つのSELECT文でまとめて 複数のテーブルを呼び出す方法と SELECT文を何度も発行する方法とがありますが、 やはり一つにまとめたほうが理想的なんでしょうか?

    • ベストアンサー
    • MySQL
  • SQLServer2005のSQL文での別名の取り扱い

    現在VB.net2005とSQLServer2005にてプログラムを組んでいます。 以下のように、サブクエリにて抽出されたStockテーブルと Tagテーブルを結合するSQL文を組みました。 *行頭は列番号です。 01- SELECT * FROM 02- ( 03-  SELECT A1.*, A3.* FROM 04-   ( 05-    SELECT A2.* FROM stock AS A2 06-    WHERE A2.StockDay < #日付#  '【SQLserverで流す時は "CONVERT(DATETIME, '日付')"】 07-    AND A2.ShopCode = '店番号' 08-   ) AS A1 09-  LEFT JOIN tag AS A3 10-  ON A1.StockNo = A3.StockNo 11- ) AS S1 これだとACCESS2000のクエリ上では正しく実行できます。 しかし、.net2005のサーバエクスプローラ上で上記SQL文を流しても、 「列 'StockNo' が 'S1' に複数回指定されました。」 とエラーが出てしまい実行することができません。 行03を "SELECT A1.* FROM" にするとSQLServer2005でも動きますが、 tagテーブルのフィールドが結果に含まれません。 tagテーブルのフィールドも結果に含みたいです。 どなたか原因や回避方法をご存知の方いらっしゃいましたら、 お手数ですが是非ともご教示頂きたいです。 よろしくお願い致します。

  • select文の書き方

    すみません、SQL初心者です。 joinで結合元の複数のカラムから結合先の同一のカラムの値を参照する方法がわかりません。 以下の場合、どうすればいいでしょうか。 テーブルseisekiとsimeiがあります。 seisekiにはテストIDとテスト毎の英語と国語のトップの生徒の生徒番号のカラムがあります。 simeiには生徒番号と生徒名カラムがあります。 2つのテーブルをjoinしてテストIDから英語と国語のトップの生徒の氏名を求める場合のselect文はどう書けば良いでしょうか?

    • ベストアンサー
    • MySQL
  • SQL CASE 文について

    開発環境 SQLSERVER VB2005 SQLのCASE文についての質問ですが、DATE型のデータが有効値の場合は”スペース”それ以外の場合は格納されているDATE型を表示したいのですが、どなたかご教授お願いいたします。下記のSQLでは全ての日付が出てしまいます。 SELECT CASE 日付 WHEN '2000/01/01' THEN ' '     ELSE 日付          END AS Expr1 FROM  テーブル CASE文以外でもできますか? よろしくお願いいたします。