web-dev-qa-db-ja.com

すべての(またはほとんどの)データベースで機能する効率的なSQLテストクエリまたは検証クエリ

多くのデータベース接続プーリングライブラリは、SQL接続のアイドル状態をテストする機能を提供します。たとえば、JDBCプーリングライブラリ c3p には preferredTestQuery というプロパティがあり、設定された間隔で接続で実行されます。同様に、Apache Commons DBCPには validationQuery があります。

多くの クエリ 私が見たのはMySQL用であり、SELECT 1;をテストクエリの値として使用することをお勧めします。ただし、このクエリは一部のデータベース(たとえば、SELECT 1FROM句を想定しているHSQLDB)では機能しません。

同様に効率的ですが、すべてのSQLデータベースで機能するデータベースに依存しないクエリはありますか?

編集:

存在しない場合(そうであると思われる)、誰かがさまざまなデータベースプロバイダーで機能する一連のSQLクエリを提案できますか?私の意図は、データベースプロバイダーの構成に基づいて、使用できるステートメントをプログラムで決定することです。

135
Rob Hruska

ここでいくつかの答えからの助けと一緒に少し研究した後:

SELECT 1

  • H2
  • MySQL
  • Microsoft SQL Server( NimChimpsky による)
  • PostgreSQL
  • SQLite

SELECT 1 FROM DUAL

  • オラクル

SELECT 1 FROM any_existing_table WHERE 1=0

または

SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS

  • HSQLDB(バージョン1.8.0.10でテスト済み)

    注:2番目のクエリでWHERE 1=0句を使用しようとしましたが、クエリが実行されないため、Apache Commons DBCPのvalidationQueryの値としては機能しませんでしたt行を返します


VALUES 1またはSELECT 1 FROM SYSIBM.SYSDUMMY1

SELECT 1 FROM SYSIBM.SYSDUMMY1

  • DB2

select count(*) from systables

  • Informix
242
Rob Hruska

ドライバーがJDBC 4に準拠している場合、接続をテストするための専用クエリは必要ありません。代わりに、接続をテストするための Connection.isValid があります。

JDBC 4は2006年のJava 6の一部であり、ドライバーはこれをサポートするはずです!

HikariCPのような有名な接続プールには、テストクエリを指定するための設定パラメーターがまだありますが、使用することは強くお勧めしません。

???? connectionTestQuery

ドライバーがJDBC4をサポートしている場合、このプロパティを設定しないことを強くお勧めします。これは、JDBC4 Connection.isValid()APIをサポートしない「レガシー」データベース用です。これは、プールから接続が与えられる直前に実行され、データベースへの接続がまだ有効であることを検証するクエリです。繰り返しますが、このプロパティなしでプールを実行してみてください。ドライバーがJDBC4に準拠していない場合、HikariCPはエラーをログに記録します。デフォルト:なし

13
Tim Büthe

残念ながら、データベースに関係なく常に機能するSELECTステートメントはありません。

ほとんどデータベースのサポート:

SELECT 1

一部のデータベースはこれをサポートしていませんが、テーブルが不要なときに使用できるDUALというテーブルがあります。

SELECT 1 FROM DUAL

MySQLは互換性の理由からこれもサポートしていますが、すべてのデータベースがサポートしているわけではありません。上記のいずれもサポートしていないデータベースの回避策は、単一の行を含むDUALと呼ばれるテーブルを作成することです。これにより、上記が機能します。

HSQLDBは​​上記のいずれもサポートしていないため、DUALテーブルを作成するか、以下を使用できます。

SELECT 1 FROM any_table_that_you_know_exists_in_your_database
6
Mark Byers

私はこれを使用します:

select max(table_catalog) as x from information_schema.tables

接続と、postgreSQL、MySQL、MSSQLのクエリ(結果として1行)を実行する機能を確認します。

2
Wojciechk

select count(*)を使用するテストでは、*がすべての列データを読み取る可能性があるため、select count(1)を使用する方が効率的です。

2
Nathan Niesen

どう?

SELECT user()

私はこれを以前に使用しました。MySQL、H2は問題ありません、他の人は知りません。

1
wener

私が使う

Select COUNT(*) As X From INFORMATION_SCHEMA.SYSTEM_USERS Where 1=0

hsqldb 1.8.0の場合

1
thinkbase

select 1はSQLサーバーで機能しますが、他のサーバーについてはわかりません。

標準のANSI SQLを使用してテーブルを作成し、そのテーブルからクエリを実行します。

1
NimChimpsky

OPがJava回答を望んでいると仮定すると:

JDBC3/Java 6の時点で、独自のメソッドを作成するのではなく、使用すべき isValid() メソッドがあります。

このメソッドIDが呼び出されたときに、ドライバーの実装者はデータベースに対して何らかのクエリを実行する必要があります。あなた-単なるJDBCユーザーとして-このクエリが何であるかを知る必要も、理解する必要もありません。必要なことは、JDBCドライバーの作成者が自分の仕事を適切に行ったことを信頼することだけです。

1
peterh

それが難しい方法を見つけた

SELECT 1 FROM DUAL

maxDBの場合も同様です。

1
Lars Decker

MSSQLの場合。

これにより、リンクサーバーが動作しているかどうかを判断できました。 Open Query接続とTRY CATCHを使用して、エラーの結果を有用なものにします。

IF OBJECT_ID('TEMPDB..#TEST_CONNECTION') IS NOT NULL DROP TABLE #TEST_CONNECTION
IF OBJECT_ID('TEMPDB..#RESULTSERROR') IS NOT NULL DROP TABLE #RESULTSERROR
IF OBJECT_ID('TEMPDB..#RESULTSGOOD') IS NOT NULL DROP TABLE #RESULTSGOOD

DECLARE @LINKEDSERVER AS VARCHAR(25)    SET @LINKEDSERVER = 'SERVER NAME GOES HERE'
DECLARE @SQL AS VARCHAR(MAX)
DECLARE @OPENQUERY AS VARCHAR(MAX)

--IF OBJECT_ID ('dbo.usp_GetErrorInfo', 'P' ) IS NOT NULL DROP PROCEDURE usp_GetErrorInfo;  
--GO  

---- Create procedure to retrieve error information.  
--CREATE PROCEDURE dbo.usp_GetErrorInfo  
--AS  
--SELECT     
--    ERROR_NUMBER() AS ErrorNumber  
--    ,ERROR_SEVERITY() AS ErrorSeverity  
--    ,ERROR_STATE() AS ErrorState  
--    ,ERROR_PROCEDURE() AS ErrorProcedure  
--    ,ERROR_LINE() AS ErrorLine  
--    ,ERROR_MESSAGE() AS Message;  
--GO  


BEGIN TRY
SET @SQL='
SELECT 1 
'''
--SELECT @SQL
SET @OPENQUERY = 'SELECT * INTO ##TEST_CONNECTION FROM OPENQUERY(['+ @LINKEDSERVER +'],''' + @SQL + ')'
--SELECT @OPENQUERY
EXEC(@OPENQUERY)
SELECT * INTO #TEST_CONNECTION FROM ##TEST_CONNECTION
DROP TABLE ##TEST_CONNECTION
--SELECT * FROM #TEST_CONNECTION
END TRY

BEGIN CATCH
-- Execute error retrieval routine.
IF OBJECT_ID('dbo.usp_GetErrorInfo') IS NOT NULL -- IT WILL ALWAYS HAVE SOMTHING... 
    BEGIN
        CREATE TABLE #RESULTSERROR (
        [ErrorNumber]       INT
        ,[ErrorSeverity]    INT
        ,[ErrorState]       INT
        ,[ErrorProcedure]   INT
        ,[ErrorLine]        INT
        ,[Message]          NVARCHAR(MAX) 
        )
        INSERT INTO #RESULTSERROR
        EXECUTE dbo.usp_GetErrorInfo
    END
END CATCH

BEGIN 
    IF (Select ERRORNUMBER FROM #RESULTSERROR WHERE ERRORNUMBER = '1038') IS NOT NULL --'1038' FOR ME SHOWED A CONNECTION ATLEAST. 
        SELECT
        '0' AS [ErrorNumber]        
        ,'0'AS [ErrorSeverity]  
        ,'0'AS [ErrorState]     
        ,'0'AS [ErrorProcedure] 
        ,'0'AS [ErrorLine]      
        , CONCAT('CONNECTION IS UP ON ', @LINKEDSERVER) AS [Message]            
    ELSE 
        SELECT * FROM #RESULTSERROR
END

docs.Microsoft.com

0
DeFlanko

Oracleの場合、パフォーマンスの高いクエリは

select 'X' from <your_small_table> where <primay_key_coulmn> = <some_value>

これはパフォーマンスの観点からです。

0
Joby Kurian

これをFirebirdに使用します

select 1 from RDB$RELATION_FIELDS rows 1
0
claudsan