|
Publicité ' | |||||||||||||||||||||||
|
|
#1 |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
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 |
|
|
00
|
|
|
#2 |
|
Membre Expert
![]() Inscription : novembre 2004 Messages : 1 298 ![]() |
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. |
|
|
00
|
|
|
#3 | |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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 |
|
|
|
00
|
|
|
#4 |
|
Membre Expert
![]() Inscription : novembre 2004 Messages : 1 298 ![]() |
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.
|
|
|
00
|
|
|
#5 | |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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ù. |
|
|
|
00
|
|
|
#6 |
|
Membre Expert
![]() Inscription : novembre 2004 Messages : 1 298 ![]() |
hum... comment s'appelle le driver ODBC ?
|
|
|
00
|
|
|
#7 |
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 638 ![]() |
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. |
|
|
00
|
|
|
#8 |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
|
|
|
00
|
|
|
#9 | |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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! |
|
|
|
00
|
|
|
#10 | |
|
Membre régulier
![]() Inscription : octobre 2006 Messages : 111 ![]() |
Citation:
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... |
|
|
|
00
|
|
|
#11 |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
|
|
|
00
|
|
|
#12 |
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 638 ![]() |
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. |
|
|
00
|
|
|
#13 | |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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) |
|
|
|
00
|
|
|
#14 | ||
|
Membre Expert
![]() Inscription : novembre 2004 Messages : 1 298 ![]() |
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 :
|
||
|
|
00
|
|
|
#15 | |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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. |
|
|
|
00
|
|
|
#16 | |
|
Membre Expert
![]() Inscription : novembre 2004 Messages : 1 298 ![]() |
Citation:
La fonction analyserait la requête et pourrait, dans l'ordre :
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. |
|
|
|
00
|
|
|
#17 |
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
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. |
|
|
00
|
|
|
#18 | |||
|
Membre du Club
![]() Inscription : novembre 2009 Messages : 76 ![]() |
Citation:
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:
Citation:
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) |
|||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com