De nombreuses bibliothèques de regroupement de connexions de base de données offrent la possibilité de tester l'inactivité des connexions SQL. Par exemple, la bibliothèque de pool JDBC c3p0 a une propriété appelée preferredTestQuery
, qui est exécutée sur la connexion à des intervalles configurés. De même, Apache Commons DBCP a validationQuery
.
De nombreux exemplerequêtes que j'ai vus sont pour MySQL et recommandent d'utiliser SELECT 1;
comme valeur pour la requête test. Toutefois, cette requête ne fonctionne pas sur certaines bases de données (par exemple, HSQLDB, pour laquelle SELECT 1
attend une clause FROM
).
Existe-t-il une requête agnostique à la base de données qui soit efficace, mais qui fonctionne pour toutes les bases de données SQL?
Modifier:
S'il n'y en a pas (ce qui semble être le cas), quelqu'un peut-il suggérer un ensemble de requêtes SQL qui fonctionneront pour différents fournisseurs de bases de données? Mon intention est de déterminer par programme une instruction que je peux utiliser en fonction de la configuration de mon fournisseur de base de données.
Après un peu de recherche avec l'aide de certaines des réponses ici:
SELECT 1
SELECT 1 FROM DUAL
SELECT 1 FROM any_existing_table WHERE 1=0
ou
SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS
HSQLDB (testé avec la version 1.8.0.10)
Remarque: j'ai essayé d'utiliser une clause WHERE 1=0
sur la seconde requête, mais cela ne fonctionnait pas comme valeur pour le validationQuery
d'Apache Commons DBCP, car la requête ne ' ne renvoie aucune ligne
VALUES 1
ou SELECT 1 FROM SYSIBM.SYSDUMMY1
SELECT 1 FROM SYSIBM.SYSDUMMY1
select count(*) from systables
Si votre pilote est compatible JDBC 4, une requête dédiée n'est pas nécessaire pour tester les connexions. Au lieu de cela, il y a Connection.isValid pour tester la connexion.
JDBC 4 fait partie de Java 6 depuis 2006 et votre pilote devrait le supporter maintenant!
Les pools de connexions célèbres, tels que HikariCP, ont toujours un paramètre config pour spécifier une requête de test, mais déconseillent fortement de l'utiliser:
???? connectionTestQuery
Si votre pilote prend en charge JDBC4, nous vous recommandons vivement recommande de ne pas définir cette propriété. Ceci concerne les bases de données "anciennes" qui ne prennent pas en charge l’API JDBC4 Connection.isValid (). C'est le requête qui sera exécutée juste avant qu'une connexion ne vous soit donnée à partir du pool pour valider que la connexion à la base de données est toujours vivant. Là encore, essayez d’exécuter la piscine sans cette propriété, HikariCP enregistrera une erreur si votre pilote n'est pas compatible JDBC4 pour vous laisser savoir. Par défaut: aucun
Malheureusement, aucune instruction SELECT ne fonctionnera toujours, quelle que soit la base de données.
Most bases de données supportées:
SELECT 1
Certaines bases de données ne supportent pas cela, mais ont une table appelée DUAL que vous pouvez utiliser quand vous n'avez pas besoin de table:
SELECT 1 FROM DUAL
MySQL le prend également en charge pour des raisons de compatibilité, mais toutes les bases de données ne le font pas. Une solution de contournement pour les bases de données qui ne prennent en charge l’un des éléments ci-dessus consiste à créer une table appelée DUAL contenant une seule ligne.
HSQLDB ne prend en charge aucun des éléments ci-dessus, vous pouvez donc créer la table DUAL ou bien utiliser:
SELECT 1 FROM any_table_that_you_know_exists_in_your_database
J'utilise celui-ci:
select max(table_catalog) as x from information_schema.tables
pour vérifier la connexion et la capacité d'exécuter des requêtes (avec 1 ligne comme résultat) pour postgreSQL, MySQL et MSSQL.
Pour les tests utilisant select count(*)
, il devrait être plus efficace d'utiliser select count(1)
car *
peut entraîner la lecture de toutes les données de colonne.
Que diriez-vous
SELECT user()
J'utilise ceci avant. MaSQL, H2 va bien, je ne connais pas les autres.
J'utilise
Select COUNT(*) As X From INFORMATION_SCHEMA.SYSTEM_USERS Where 1=0
pour hsqldb 1.8.0
select 1
fonctionnerait sur un serveur SQL, pas sûr des autres.
Utilisez ansi sql standard pour créer une table, puis interrogez-la à partir de cette table.
En supposant que le PO souhaite une réponse Java:
Depuis JDBC3/Java 6, il existe la méthode isValid () qui devrait être utilisée plutôt que d'inventer sa propre méthode.
L'implémenteur du pilote est tenu d'exécuter une sorte de requête sur la base de données lorsque cet identificateur de méthode est appelé. En tant que simple utilisateur de JDBC, vous n'avez pas besoin de savoir ou de comprendre en quoi consiste cette requête. Tout ce que vous avez à faire est de faire confiance au créateur du pilote JDBC qui a effectué son travail correctement.
Je viens de découvrir à la dure qu'il est
SELECT 1 FROM DUAL
pour MaxDB aussi.
Pour MSSQL.
Cela m'a aidé à déterminer si les serveurs liés étaient en vie. Utilisation d'une connexion Open Query et d'un TRY CATCH pour que les résultats de l'erreur soient utiles.
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
Pour Oracle, la requête hautement performante sera
select 'X' from <your_small_table> where <primay_key_coulmn> = <some_value>
C'est du point de vue de la performance.
Je l'utilise pour Firebird
select 1 from RDB$RELATION_FIELDS rows 1