Précédent   Forum des professionnels en informatique > Systèmes > Autres systèmes > AS/400
AS/400 Le Forum d'entraide sur IBM AS/400 - iSeries. RPG.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/02/2011, 11h18   #1
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Par défaut ODBC et '++..'

Une valeur qui n'a pas de sens est affichée comme '++++++' dans STRSQL et 'Run SQL Script'.
Par exemple:
create table test (i int);
insert into test values(0);
select i, i/i, i+i from test;
=>
0 '++++++++++' 0
et SQL +802 (seulement un warning, contrairement à l'erreur -802) reason 8 divide by zero.

Dans une application ODBC comment cette valeur particulière '+++++++++' se reçoit-elle? Les api ODBC semblent retourner simplement la valeur NULL.

D'autre part y a-t-il moyen de faire échouer la requête avec SQL-802 (et non +802) plutôt que de délivrer ce résultat bizarre ('++++++++') non prévu par les outils de queries ODBC courants qui se contentent de recevoir la valeur NULL comme si de rien n'était.
Merci à tous,
Fred
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 13h50   #2
Membre Expert
 
Inscription : novembre 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 1 298
Points : 1 355
Points : 1 355
Quel langage côté client ?

Colle ici la chaîne de connexion ODBC et les lignes du script client où tu récupères les infos des tables par SQL.
Mercure est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 14h35   #3
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par Mercure Voir le message
Quel langage côté client ?
Colle ici la chaîne de connexion ODBC et les lignes du script client où tu récupères les infos des tables par SQL.
Par exemple en faisant dans excel 2003 menu data=>import external data=>new database query
et simplement taper le query select i, i/i, i+i from test
tout se passe comme si i/i valait NULL

Ou bien de SAS, les appels ODBC donnent:
4 create table data as select * from connection to odbc (
5 select i, i/i, i+i from test
6 );
ODBC: ENTER SQLGetConnectAttr
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06ead62c
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLGetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06ead62c (1) <SQL_AUTCOMMIT_ON>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetConnectAttr
0x060f1a20
101 <SQL_ACCESS_MODE>
1 <SQL_MODE_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
101 <SQL_ACCESS_MODE>
1 <SQL_MODE_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetConnectAttr
0x060f1a20
108 <SQL_TXN_ISOLATION>
2 <SQL_TXN_READ_COMMITTED>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
108 <SQL_TXN_ISOLATION>
2 <SQL_TXN_READ_COMMITTED>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLGetConnectAttr
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06ead8f0
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLGetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06ead8f0 (1) <SQL_AUTCOMMIT_ON>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetConnectAttr
0x060f1a20
101 <SQL_ACCESS_MODE>
1 <SQL_MODE_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
101 <SQL_ACCESS_MODE>
1 <SQL_MODE_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetConnectAttr
0x060f1a20
108 <SQL_TXN_ISOLATION>
2 <SQL_TXN_READ_COMMITTED>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
108 <SQL_TXN_ISOLATION>
2 <SQL_TXN_READ_COMMITTED>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLAllocHandle
3 <SQL_HANDLE_STMT>
0x060f1a20
0x03b67004
ODBC: EXIT SQLAllocHandle with return code 0 (SQL_SUCCESS)
3 <SQL_HANDLE_STMT>
0x060f1a20
0x03b67004 (0x060f2650)
ODBC: ENTER SQLSetStmtAttr
0x060f2650
7 <SQL_ATTR_CONCURRENCY>
1 <SQL_CONCUR_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetStmtAttr with return code 0 (SQL_SUCCESS)
0x060f2650
7 <SQL_ATTR_CONCURRENCY>
1 <SQL_CONCUR_READ_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetStmtAttr
0x060f2650
1 <SQL_ATTR_MAX_ROWS>
0
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetStmtAttr with return code 0 (SQL_SUCCESS)
0x060f2650
1 <SQL_ATTR_MAX_ROWS>
0
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLSetStmtAttr
0x060f2650
6 <SQL_ATTR_CURSOR_TYPE>
0 <SQL_CURSOR_FORWARD_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLSetStmtAttr with return code 0 (SQL_SUCCESS)
0x060f2650
6 <SQL_ATTR_CURSOR_TYPE>
0 <SQL_CURSOR_FORWARD_ONLY>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLFreeStmt
0x060f2040
0 <SQL_CLOSE>
ODBC: EXIT SQLFreeStmt with return code 0 (SQL_SUCCESS)
0x060f2040
0 <SQL_CLOSE>
ODBC: ENTER SQLPrepare
0x060f2650
0x03b66520 [ 28] "select i, i/i, i+i from test"
28
ODBC: EXIT SQLPrepare with return code 0 (SQL_SUCCESS)
0x060f2650
0x03b66520 [ 28] "select i, i/i, i+i from test"
28
ODBC: ENTER SQLNumResultCols
0x060f2650
0x06eadad6
ODBC: EXIT SQLNumResultCols with return code 0 (SQL_SUCCESS)
0x060f2650
0x06eadad6 (3)
ODBC: ENTER SQLDescribeCol
0x060f2650
1
0x03b67904
129
0x03b67986
0x03b67988
0x03b6798c
0x03b67990
0x03b67992
ODBC: EXIT SQLDescribeCol with return code 0 (SQL_SUCCESS)
0x060f2650
1
0x03b67904 [ 1] "I"
129
0x03b67986 (1)
0x03b67988 (4) <SQL_INTEGER>
0x03b6798c (10)
0x03b67990 (0)
0x03b67992 (1)
ODBC: ENTER SQLColAttribute
0x060f2650
1
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67998
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
1
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67998 (4)
ODBC: ENTER SQLColAttribute
0x060f2650
1
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b679ac
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
1
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b679ac (0)
ODBC: ENTER SQLDescribeCol
0x060f2650
2
0x03b679b8
129
0x03b67a3a
0x03b67a3c
0x03b67a40
0x03b67a44
0x03b67a46
ODBC: EXIT SQLDescribeCol with return code 0 (SQL_SUCCESS)
0x060f2650
2
0x03b679b8 [ 5] "00002"
129
0x03b67a3a (5)
0x03b67a3c (4) <SQL_INTEGER>
0x03b67a40 (10)
0x03b67a44 (0)
0x03b67a46 (1)
ODBC: ENTER SQLColAttribute
0x060f2650
2
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67a4c
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
2
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67a4c (4)
ODBC: ENTER SQLColAttribute
0x060f2650
2
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b67a60
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
2
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b67a60 (0)
ODBC: ENTER SQLDescribeCol
0x060f2650
3
0x03b67a6c
129
0x03b67aee
0x03b67af0
0x03b67af4
0x03b67af8
0x03b67afa
ODBC: EXIT SQLDescribeCol with return code 0 (SQL_SUCCESS)
0x060f2650
3
0x03b67a6c [ 5] "00003"
129
0x03b67aee (5)
0x03b67af0 (4) <SQL_INTEGER>
0x03b67af4 (10)
0x03b67af8 (0)
0x03b67afa (1)
ODBC: ENTER SQLColAttribute
0x060f2650
3
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67b00
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
3
3 <SQL_DESC_OCTET_LENGTH>
0x00000000
0
0x00000000
0x03b67b00 (4)
ODBC: ENTER SQLColAttribute
0x060f2650
3
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b67b14
ODBC: EXIT SQLColAttribute with return code 0 (SQL_SUCCESS)
0x060f2650
3
9 <SQL_DESC_FIXED_PREC_SCALE>
0x00000000
0
0x00000000
0x03b67b14 (0)
ODBC: ENTER SQLEndTran
2 <SQL_HANDLE_DBC>
0x060f1a20
0 <SQL_COMMIT>
ODBC: EXIT SQLEndTran with return code 0 (SQL_SUCCESS)
2 <SQL_HANDLE_DBC>
0x060f1a20
0 <SQL_COMMIT>
ODBC: ENTER SQLBindCol
0x060f2650
1
8 <SQL_C_DOUBLE>
0x03b6b380
8
0x03b679a0
ODBC: EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
0x060f2650
1
8 <SQL_C_DOUBLE>
0x03b6b380
8
0x03b679a0
ODBC: ENTER SQLBindCol
0x060f2650
2
8 <SQL_C_DOUBLE>
0x03b6b388
8
0x03b67a54
ODBC: EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
0x060f2650
2
8 <SQL_C_DOUBLE>
0x03b6b388
8
0x03b67a54
ODBC: ENTER SQLBindCol
0x060f2650
3
8 <SQL_C_DOUBLE>
0x03b6b390
8
0x03b67b08
ODBC: EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
0x060f2650
3
8 <SQL_C_DOUBLE>
0x03b6b390
8
0x03b67b08
ODBC: ENTER SQLExecute
0x060f2650
ODBC: EXIT SQLExecute with return code 0 (SQL_SUCCESS)
0x060f2650
ODBC: ENTER SQLFetch
0x060f2650
ODBC: EXIT SQLFetch with return code 0 (SQL_SUCCESS)
0x060f2650
ODBC: ENTER SQLFetch
0x060f2650
ODBC: EXIT SQLFetch with return code 100 (SQL_NO_DATA_FOUND)
0x060f2650
NOTE: Table WORK.DATA created, with 1 rows and 3 columns.

ODBC: ENTER SQLFreeStmt
0x060f2650
0 <SQL_CLOSE>
ODBC: EXIT SQLFreeStmt with return code 0 (SQL_SUCCESS)
0x060f2650
0 <SQL_CLOSE>
ODBC: ENTER SQLFreeStmt
0x060f2650
0 <SQL_CLOSE>
ODBC: EXIT SQLFreeStmt with return code 0 (SQL_SUCCESS)
0x060f2650
0 <SQL_CLOSE>
ODBC: ENTER SQLFreeHandle
3 <SQL_HANDLE_STMT>
0x060f2650
ODBC: EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
3 <SQL_HANDLE_STMT>
0x060f2650
7 quit;
ODBC: ENTER SQLGetConnectAttr
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06eafe58
-6 <SQL_IS_INTEGER>
ODBC: EXIT SQLGetConnectAttr with return code 0 (SQL_SUCCESS)
0x060f1a20
102 <SQL_ATTR_AUTOCOMMIT>
0x06eafe58 (1) <SQL_AUTCOMMIT_ON>
-6 <SQL_IS_INTEGER>
ODBC: ENTER SQLFreeHandle
3 <SQL_HANDLE_STMT>
0x060f2040
ODBC: EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
3 <SQL_HANDLE_STMT>
0x060f2040
ODBC: ENTER SQLDisconnect
0x060f1a20
ODBC: EXIT SQLDisconnect with return code 0 (SQL_SUCCESS)
0x060f1a20
ODBC: ENTER SQLFreeHandle
1 <SQL_HANDLE_ENV>
0x060f1978
ODBC: EXIT SQLFreeHandle with return code 0 (SQL_SUCCESS)
1 <SQL_HANDLE_ENV>
0x060f1978
NOTE: PROCEDURE SQL used (Total process time):
real time 1.29 seconds
cpu time 0.59 seconds
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 16h12   #4
Membre Expert
 
Inscription : novembre 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 1 298
Points : 1 355
Points : 1 355
Je ne vois pas trop de solution simple à mettre en oeuvre et puis je ne connais pas SAS. Toutefois, je ne sais pas si c'est une option envisageable pour toi mais perso, j'aurais plutôt écrit une procédure stockée dans laquelle j'aurais exécuté ma ou mes requêtes SQL et renvoyé au client un indicateur OK ou pas OK selon que le traitement dans la procédure s'est bien ou mal passé. Pour le savoir, je mettrais ma procédure sous debug et récupérerais les messages CPF et/ou SQL renvoyés par l'OS et/ou SQL Manager lors de la division par zéro ou toute autre anomalie.
Mercure est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 16h59   #5
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par Mercure Voir le message
Je ne vois pas trop de solution simple à mettre en oeuvre et puis je ne connais pas SAS. Toutefois, je ne sais pas si c'est une option envisageable pour toi mais perso, j'aurais plutôt écrit une procédure stockée dans laquelle j'aurais exécuté ma ou mes requêtes SQL et renvoyé au client un indicateur OK ou pas OK selon que le traitement dans la procédure s'est bien ou mal passé. Pour le savoir, je mettrais ma procédure sous debug et récupérerais les messages CPF et/ou SQL renvoyés par l'OS et/ou SQL Manager lors de la division par zéro ou toute autre anomalie.
Tout à fait d'accord, c'est une très bonne idée.
Mais le souci ici c'est qu'il s'agit de requêtes "écrites" par des "utilisateurs avancés" avec l'un ou l'autre outil qui se connecte à l'AS400 par ODBC (excel et SAS ne sont que 2 exemples).
Le problème c'est que pour eux quand ils produisent une requête de ce genre (pas aussi caricatural que l'exemple ici, il y a des exemples plus fins où le fait que la requête produise des erreurs est beaucoup moins visible) et bien ils reçoivent un résultat comme si de rien n'était et travaillent ensuite sur base de ces données comme si elles étaient correctes. Tout ceci n'arriverait pas si on recevait d'office une erreur au lieu d'un warning plus cette étrange valeur '++++++++' dont la définition m'échappe dans le standard ODBC. A moins qu'il n'y ait l'équivalent de qqchose comme "not a number" ou "not a value" mais différent de NULL dans le standard 0DBC? Mais je ne vois pas où.
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 17h26   #6
Membre Expert
 
Inscription : novembre 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 1 298
Points : 1 355
Points : 1 355
hum... comment s'appelle le driver ODBC ?
Mercure est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 17h36   #7
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
le problème c'est qu'une division par zéro ne renvoie pas null en mathématique, et c'est ce qu'a modélisé ici db2 (je suppose ? :p )

Ce que je trouve étrange, par contre, c'est que l'erreur est gravité 30, selon mon historique, mais que ca marche même.

Bref, s'il n'existe pas de variable système pour régler ca, une simple utilisation d'un CASE / WHEN devrait régler le problème.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 18h37   #8
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par Mercure Voir le message
hum... comment s'appelle le driver ODBC ?
C'est Client Access ODBC Driver (32-bit) 13.00.01.00

Normalement c'est un bon ;-)
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/02/2011, 18h41   #9
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par punkoff Voir le message
le problème c'est qu'une division par zéro ne renvoie pas null en mathématique, et c'est ce qu'a modélisé ici db2
DB2 fait ce qu'il peut pour renvoyer un résultat, même en cas de division par zéro.
Mais parfois il n'y arrive pas:
select i/i from test order by 1
=> pas de résultat et SQL-802.
select i/i from test
=> résultat "spécial" et SQL+802.

Je trouverais quand même beaucoup plus cohérent de renvoyer pas de résultat et SQL-802 dans les 2 cas!
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 08h04   #10
Membre régulier
 
Inscription : octobre 2006
Messages : 111
Détails du profil
Informations forums :
Inscription : octobre 2006
Messages : 111
Points : 92
Points : 92
Citation:
Envoyé par frfancha Voir le message
DB2 fait ce qu'il peut pour renvoyer un résultat, même en cas de division par zéro.
Mais parfois il n'y arrive pas:
select i/i from test order by 1
=> pas de résultat et SQL-802.
select i/i from test
=> résultat "spécial" et SQL+802.

Je trouverais quand même beaucoup plus cohérent de renvoyer pas de résultat et SQL-802 dans les 2 cas!
Non pour moi c'est cohérent.
Dans le premier exemple, il ne peut renvoyer d'enregistrement, puisqu'il n'a aucune valeur à classer et que tu lui demandes justement un classement.
Dans le second exemple, il y bien retour d'un enregistrement, c'est juste la valeur de la zone qui n'est pas affichable et pour cause...
m4k-Hurrican est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 09h28   #11
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par m4k-Hurrican Voir le message
Non pour moi c'est cohérent.
Dans le premier exemple, il ne peut renvoyer d'enregistrement, puisqu'il n'a aucune valeur à classer
?? select null from test order by 1

fonctionne très bien
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 10h19   #12
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
Sauf que Null n'est pas une valeur, on ne peut faire de test d'égalité dessus.

C'est plutôt un état, et c'est supporté dans les schéma relationnelle.

Là on a affaire à une division par 0 qui retourne une valeur indéterminable.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 12h00   #13
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par punkoff Voir le message
Sauf que Null n'est pas une valeur, on ne peut faire de test d'égalité dessus.
C'est plutôt un état, et c'est supporté dans les schéma relationnelle.
Là on a affaire à une division par 0 qui retourne une valeur indéterminable.
Oui, comme tu dis: null est supporté dans les schémas relationels.
Par contre ici c'est une "bête" d'une autre nature, qui devrait être non supportée au lieu de parfois oui (sans le order by) et parfois non (avec le order by)
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 14h30   #14
Membre Expert
 
Inscription : novembre 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 1 298
Points : 1 355
Points : 1 355
Tu pourrais essayer de prévoir que telle ou telle colonne risque d'être nulle ou divisée par zéro en la testant dans la select et en renvoyant une valeur valide au client.

Code :
1
2
3
SELECT IFNULL(MaColonne, 0), 

SELECT CASE ColonneDiviseur When 0 Then 1 Else ColonneDiviseur END,
Je sais, je sais, c'est un peu ch... mais ça peut quand même te dépanner faute de mieux.
Mercure est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 15h16   #15
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par Mercure Voir le message
Tu pourrais essayer de prévoir que telle ou telle colonne risque d'être nulle ou divisée par zéro en la testant dans la select et en renvoyant une valeur valide au client.
Pas terrible car l'utilisateur écrit le query.

Mais il "l'envoie" à l'AS400 en SAS par une macro qui se charge de mettre le statement connecte to ODBC, select from, ...

=> je vais essayer ton idée de la stored procedure en changeant la macro pour envoyer le statement à une stored procedure qui exécute le query (execute immediate 'create table qtemp/mytable as (varStmt) with data') en sauvant le résultat dans QTEMP/myTable seulement si aucun warning, y compris par exemple SQL+802, puis lire le résultat qui se trouve dans QTEMP/myTable (non, il n'est pas possible de faire une stored procedure qui reourne un result set ce n'est pas exploitable en SAS).

Si ca marche je vous dis quoi.

Je continue à penser que c'est malsain que DB2 renvoie un résultat "partiel" via l'ODBC avec un warning au lieu d'une erreur systématique, mais bon.
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 12h09   #16
Membre Expert
 
Inscription : novembre 2004
Messages : 1 298
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 1 298
Points : 1 355
Points : 1 355
Citation:
Envoyé par frfancha
=> je vais essayer ton idée de la stored procedure en changeant la macro pour envoyer le statement à une stored procedure qui exécute le query (execute immediate 'create table qtemp/mytable as (varStmt) with data') en sauvant le résultat dans QTEMP/myTable seulement si aucun warning, y compris par exemple SQL+802, puis lire le résultat qui se trouve dans QTEMP/myTable (non, il n'est pas possible de faire une stored procedure qui reourne un result set ce n'est pas exploitable en SAS).
Pourquoi faire une stored procedure qui va créer une table puis la lire, ce qui va coûter cher en I/O et pénaliser les temps de traitement, alors que j'ai tout de même l'impression qu'une simple fonction SQL qui contrôlerait la syntaxe de la requête et qui renverrait en cas d'erreur le SQLCODE et/ou un indicateur au client suffirait ?

La fonction analyserait la requête et pourrait, dans l'ordre :
  1. formater toutes les divisions avec un

    "CASE ColonneDiviseur When 0 Then 1 Else ColonneDiviseur END"

    L'exemple de ton premier post deviendrait :
    Code :
    select i, i/CASE i When 0 Then 1 Else i END, i+i from test
    et c'est cette requête qui serait soumise au moteur SQL.

  2. contrôler la syntaxe de la requête avec le programme CL SYNSQL (joint à ce post) qui fait appel à l'API QSQCHKS à voir sur le site de Big Blue.

    NB : Le contrôle pourrait se faire alternativement avec une instruction PREPARE qui fait une vérification plus approfondie qu'un simple contrôle de syntaxe.
Il serait alors inutile d'exécuter la requête dans un fichier QTEMP, le contrôle de syntaxe semblant suffisant.

Un dernier mot pour dire que SAS n'est pas du tout adapté pour faire le travail que veulent les utilisateurs puiqu'il ne sait pas lire un record set.
Fichiers attachés
Type de fichier : zip synsql.zip (845 octets, 4 affichages)
Mercure est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 16h19   #17
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Par défaut Info peut-être utile

Info peut-être utile:

Le fait que:
select 0/0 from table
retourne un warning, mais que:
select 0/0 from table order by 1
retourne une erreur

peut être rendu cohérent (warning dans les 2 cas, je préférerais de loin erreur dans les 2 cas, mais bon), par:

INSERT INTO (QSYS/)QAQQINI VALUES('COLLATE_ERRORS','*YES', default)

Notez que le warning SQL+802 correspond au SQLSTATE 01564 qui est bien transmis en JDBC (en tout cas dans run sql scripts), mais si vous faites une trace ODBC vous verrez que seul le SQLSTATE 01000 (qui n'est qu'un warning "normal" contrairement au 01564) apparaît avec le SQL+802.
IBM est en train d'examiner pq JDBC ok et ODBC pas.
Quand j'ai plus d'info je vous dis quoi.
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 16h33   #18
Membre du Club
 
Inscription : novembre 2009
Messages : 76
Détails du profil
Informations forums :
Inscription : novembre 2009
Messages : 76
Points : 66
Points : 66
Citation:
Envoyé par Mercure Voir le message
Pourquoi faire une stored procedure qui va créer une table puis la lire, ce qui va coûter cher en I/O et pénaliser les temps de traitement
C'est vrai, mais les queries concernés lisent énormément de rows, et en retournent très peu (group by et autres limitant le résultat à finalement renvoyer).
Donc c'est vrai ca paraît un "c.." d'écrire dans QTEMP juste pour le lire après mais dans notre cas ce ne sera pas trop pénalisant.

Citation:
Envoyé par Mercure Voir le message
alors que j'ai tout de même l'impression qu'une simple fonction SQL qui contrôlerait la syntaxe de la requête et qui renverrait en cas d'erreur le SQLCODE et/ou un indicateur au client suffirait ?
La syntaxe des queries est exacte (et quand elle ne l'est pas l'utilisateur reçoit un message de toute façon (en général SQL Code -104)).

Citation:
Envoyé par Mercure Voir le message
La fonction analyserait la requête et pourrait, dans l'ordre : [LIST=1][*]formater toutes les divisions avec un
"CASE ColonneDiviseur When 0 Then 1 Else ColonneDiviseur END"
L'exemple de ton premier post deviendrait :
Code :
select i, i/CASE i When 0 Then 1 Else i END, i+i from test
et c'est cette requête qui serait soumise au moteur SQL.
Oops, loin de nous l'idée et le temps d'écrire et de maintenir un analyseur de syntaxe SQL.

Citation:
Envoyé par Mercure Voir le message
Un dernier mot pour dire que SAS n'est pas du tout adapté pour faire le travail que veulent les utilisateurs puiqu'il ne sait pas lire un record set.
Au contraire SAS est un outil extrèment souple et puissant pour faire toute analyse utilisant des données. (son seul inconvénient est son prix très élevé, ca c'est vrai)
frfancha est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 13h46.


 
 
 
 
Partenaires

Hébergement Web