多くのデータベース接続プーリングライブラリは、SQL接続のアイドル状態をテストする機能を提供します。たとえば、JDBCプーリングライブラリ c3p には preferredTestQuery
というプロパティがあり、設定された間隔で接続で実行されます。同様に、Apache Commons DBCPには validationQuery
があります。
多くの 例クエリ 私が見たのはMySQL用であり、SELECT 1;
をテストクエリの値として使用することをお勧めします。ただし、このクエリは一部のデータベース(たとえば、SELECT 1
がFROM
句を想定しているHSQLDB)では機能しません。
同様に効率的ですが、すべてのSQLデータベースで機能するデータベースに依存しないクエリはありますか?
編集:
存在しない場合(そうであると思われる)、誰かがさまざまなデータベースプロバイダーで機能する一連のSQLクエリを提案できますか?私の意図は、データベースプロバイダーの構成に基づいて、使用できるステートメントをプログラムで決定することです。
ここでいくつかの答えからの助けと一緒に少し研究した後:
SELECT 1
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
select count(*) from systables
ドライバーがJDBC 4に準拠している場合、接続をテストするための専用クエリは必要ありません。代わりに、接続をテストするための Connection.isValid があります。
JDBC 4は2006年のJava 6の一部であり、ドライバーはこれをサポートするはずです!
HikariCPのような有名な接続プールには、テストクエリを指定するための設定パラメーターがまだありますが、使用することは強くお勧めしません。
???? connectionTestQuery
ドライバーがJDBC4をサポートしている場合、このプロパティを設定しないことを強くお勧めします。これは、JDBC4 Connection.isValid()APIをサポートしない「レガシー」データベース用です。これは、プールから接続が与えられる直前に実行され、データベースへの接続がまだ有効であることを検証するクエリです。繰り返しますが、このプロパティなしでプールを実行してみてください。ドライバーがJDBC4に準拠していない場合、HikariCPはエラーをログに記録します。デフォルト:なし
残念ながら、データベースに関係なく常に機能するSELECTステートメントはありません。
ほとんどデータベースのサポート:
SELECT 1
一部のデータベースはこれをサポートしていませんが、テーブルが不要なときに使用できるDUALというテーブルがあります。
SELECT 1 FROM DUAL
MySQLは互換性の理由からこれもサポートしていますが、すべてのデータベースがサポートしているわけではありません。上記のいずれもサポートしていないデータベースの回避策は、単一の行を含むDUALと呼ばれるテーブルを作成することです。これにより、上記が機能します。
HSQLDBは上記のいずれもサポートしていないため、DUALテーブルを作成するか、以下を使用できます。
SELECT 1 FROM any_table_that_you_know_exists_in_your_database
私はこれを使用します:
select max(table_catalog) as x from information_schema.tables
接続と、postgreSQL、MySQL、MSSQLのクエリ(結果として1行)を実行する機能を確認します。
select count(*)
を使用するテストでは、*
がすべての列データを読み取る可能性があるため、select count(1)
を使用する方が効率的です。
どう?
SELECT user()
私はこれを以前に使用しました。MySQL、H2は問題ありません、他の人は知りません。
私が使う
Select COUNT(*) As X From INFORMATION_SCHEMA.SYSTEM_USERS Where 1=0
hsqldb 1.8.0の場合
select 1
はSQLサーバーで機能しますが、他のサーバーについてはわかりません。
標準のANSI SQLを使用してテーブルを作成し、そのテーブルからクエリを実行します。
OPがJava回答を望んでいると仮定すると:
JDBC3/Java 6の時点で、独自のメソッドを作成するのではなく、使用すべき isValid() メソッドがあります。
このメソッドIDが呼び出されたときに、ドライバーの実装者はデータベースに対して何らかのクエリを実行する必要があります。あなた-単なるJDBCユーザーとして-このクエリが何であるかを知る必要も、理解する必要もありません。必要なことは、JDBCドライバーの作成者が自分の仕事を適切に行ったことを信頼することだけです。
それが難しい方法を見つけた
SELECT 1 FROM DUAL
maxDBの場合も同様です。
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
Oracleの場合、パフォーマンスの高いクエリは
select 'X' from <your_small_table> where <primay_key_coulmn> = <some_value>
これはパフォーマンスの観点からです。
これをFirebirdに使用します
select 1 from RDB$RELATION_FIELDS rows 1