web-dev-qa-db-fra.com

Requête de test SQL efficace ou requête de validation qui fonctionnera sur toutes les bases de données (ou la plupart)

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.

124
Rob Hruska

Après un peu de recherche avec l'aide de certaines des réponses ici:

SELECT 1

  • H2
  • MySQL
  • Microsoft SQL Server (selon NimChimpsky )
  • PostgreSQL
  • SQLite

SELECT 1 FROM DUAL

  • Oracle

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

  • DB2

select count(*) from systables

  • Informix
242
Rob Hruska

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

11
Tim Büthe

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
5
Mark Byers

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.

2
Wojciechk

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.

2
Nathan Niesen

Que diriez-vous

SELECT user()

J'utilise ceci avant. MaSQL, H2 va bien, je ne connais pas les autres.

1
wener

J'utilise

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

pour hsqldb 1.8.0

1
thinkbase

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.

1
NimChimpsky

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.

1
peterh

Je viens de découvrir à la dure qu'il est

SELECT 1 FROM DUAL

pour MaxDB aussi.

1
Lars Decker

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

docs.Microsoft.com

0
DeFlanko

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.

0
Joby Kurian

Je l'utilise pour Firebird

select 1 from RDB$RELATION_FIELDS rows 1
0
claudsan