Utilisation des procédures stockées et des fonctions définies par l'utilisateur
Blackfish SQL utilise les procédures stockées pour encapsuler la logique métier dans le schéma d'une base de données. Blackfish SQL utilise les fonctions définies par l'utilisateur (FDU) pour étendre la prise en charge intégrée de SQL. Alors que beaucoup d'autres fournisseurs de bases de données ont inventé pour les procédures stockées leur propre pseudo-SQL, Blackfish SQL peut accéder aux procédures stockées et aux FDU créées avec n'importe quel langage .NET, comme Delphi, C#, VB et Java.
De plus, les procédures stockées peuvent augmenter les performances d'une application car elles sont exécutées dans la même machine virtuelle que le moteur de la base de données Blackfish SQL. Il en résulte une exécution dans un temps système minimal. Pendant qu'une procédure stockée exécute des instructions SQL, aucun trafic n'est généré sur le réseau. La procédure stockée utilise une connexion ADO.NET du processus. Cela offre, quant aux performances, le même avantage que l'utilisation d'un pilote ADO.NET du processus Blackfish SQL, à la place d'un pilote distant.
Les procédures stockées et les FDU présentent les avantages supplémentaires suivants :
- La logique métier, comme les contraintes d'intégrité, est isolée dans le moteur de la base de données, où elle est accessible, et imposée, à tous les clients.
- Les données sont traités localement, ce qui est plus rapide que de les envoyer vers un client ou depuis un client.
- Le langage Blackfish SQL peut être étendu par l'utilisation des fonctions C#, Delphi ou Visual Basic.
- Les performances ne sont pas pénalisées car les procédures stockées sont exécutées dans la même machine virtuelle que la base de données elle-même.
- Vous pouvez déboguer les procédures stockées .NET de la même manière que l'application client.
Ce chapitre contient les sections suivantes :
- A propos des procédures stockées
- A propos des fonctions définies par l'utilisateur (FDU)
- Création de procédures stockées pour la plate-forme .NET
- Débogage des procédures stockées .NET
- Utilisation d'une procédure stockée pour produire un IDataReader ADO.NET
- Création de procédures stockées pour la plate-forme Java
A propos des procédures stockées
Les procédures stockées sont des procédures stockées sur le serveur de la base de données et exécutées à la demande d'un client SQL. Généralement, la procédure stockée exécute plusieurs requêtes SQL sur les tables de la base de données afin de produire le résultat souhaité. Dans Blackfish SQL, ces requêtes SQL seront écrites dans le langage de votre choix parmi ceux disponibles sur les plates-formes .NET ou Java. Le but visé peut être la mise à jour d'un ensemble de tables, ou le calcul d'une valeur cumulative à partir d'une ou de plusieurs tables, ou l'ajout de contraintes d'intégrité spéciales. Une procédure stockée peut admettre plusieurs paramètres, qui peuvent être en entrée uniquement, en sortie uniquement, ou en entrée et en sortie.
Exemple
Considérez une procédure ADD_ORDER : elle prend un customerId, une itemId et une quantity comme valeurs d'entrée, et ajoute un enregistrement à la table ORDERS. Supposez que vous vouliez aussi vérifier que ce client a payé toutes ses factures précédentes. Et, si ce n'est pas le cas, vous voulez que la procédure déclenche une exception.
La procédure stockée est exécutée avec un objet IDbCommand en définissant les propriétés CommandType et CommandText, et en ajoutant les paramètres appropriés.
| CommandText | CommandType | Paramètres |
|---|---|---|
|
'CALL ADD_ORDER(?,?,?)' |
CommandType.Text |
Ajoutés dans l'ordre gauche vers droite |
|
'CALL ADD_ORDER(:CUSTID,:ITEMID,:QUANTITY)' |
CommandType.Text |
Ajoutés dans l'ordre des noms de marqueurs |
|
'ADD_ORDER' |
CommandType.StoredProcedure |
Ajoutés dans l'ordre des noms de paramètres |
Notez que l'interprétation des paramètres est différente selon la combinaison du CommandType et du style des marqueurs de paramètres. Si le CommandType est StoredProcedure, les noms des paramètres sont tirés de l'implémentation de la procédure stockée ; en ce cas, les paramètres optionnels peuvent être omis.
A propos des fonctions définies par l'utilisateur (FDU)
Une Fonction Définie par l'Utilisateur est un snippet de code écrit pour étendre la prise en charge intégrée de SQL. Comme les procédures stockées, elles sont exécutées sur le serveur de la base de données et appelées depuis un client SQL. Les FDU doivent renvoyer une valeur, elles sont habituellement utilisées dans la clause WHERE des requêtes SELECT. Cependant, une FDU peut aussi s'appeler elle-même, ainsi qu'une procédure stockée.
Exemple
Considérez une fonction MAX_VALUE qui prend deux valeurs, <valeur1> et <valeur2>, et qui renvoie la plus grande d'entre elles. La FDU peut être exécutée dans une instruction SQL :
'SELECT * FROM PEOPLE WHERE MAX_VALUE(HEIGHT,5*WIDTH) < ?'
Ou, dans une instruction SQL CALL :
'?=CALL MAX_VALUE(?,?)'
Création de procédures stockées pour la plate-forme .NET
Cette section détaille comment créer des procédures stockées et des FDU Blackfish SQL pour les plates-formes .NET.
Création d'une procédure stockée pour une base de données Blackfish SQL
Trois étapes sont nécessaires à la création d'une procédure stockée Blackfish SQL :
- Ecrivez le code de la procédure stockée en tant que membre public statique d'une classe.
- Construisez un assemblage à partir des procédures stockées. Blackfish SQL doit pouvoir localiser l'assemblage. Si vous développez dans Delphi, Blackfish SQL peut trouver l'assemblage dans BDSCOMMONDIR. Il n'est donc pas nécessaire de placer l'assemblage à un endroit spécial. Pour le déploiement, nous vous recommandons de copier l'assemblage dans le sous-répertoire où réside l'exécutable du serveur Blackfish SQL (BSQLServer.exe), ou de l'installer dans le GAC (Global Assembly Cache).
- Créez la liaison entre un identificateur SQL et le membre de l'assemblage.
Exemple
Cet exemple utilise ADD_ORDER de l'exemple de la section précédente A propos des procédures stockées, avec le schéma suivant :
TABLE CUSTOMER
| Champ | Type | Description |
|---|---|---|
|
CUST_ID |
INT |
Identificateur du client |
|
CREDIT |
DECIMAL(10,2) |
Montant du crédit accessible au client |
|
NAME |
VARCHAR(80) |
Nom du client |
TABLE ORDERS
| Champ | Type | Description |
|---|---|---|
|
CUST_ID |
INT |
Identificateur du client |
|
ITEM_ID |
INT |
Identificateur de l'article |
|
QUANTITY |
INT |
Nombre d'articles |
|
SALE_AMOUNT |
DECIMAL(10,2) |
Montant total de l'achat |
|
PAID |
DECIMAL(10,2) |
Montant payé |
TABLE ITEMS
| Champ | Type | Description |
|---|---|---|
|
ITEM_ID |
INT |
Identificateur de l'article |
|
NAME |
VARCHAR(60) |
Nom de l'article |
|
PRICE |
DECIMAL(10,2) |
Prix unitaire |
|
STOCK |
INT |
Nombre d'articles en stock |
Etape 1 : Ecrivez le code de la procédure stockée.
- Créez un package Delphi.NET et nommez-le MyProcs.dll.
- Ajoutez une référence à System.Data.dll.
- Ajoutez une unité :
P1 := Command.Parameters.Add('P1', DbType.Decimal);
P2 := Command.Parameters.Add('P2', DbType.Int32);
P1.Direction := ParameterDirection.Output;
P2.Value := CustId;
Command.ExecuteNonQuery;
if P1.Value = DBNull.Value then
Owed := 0
else
Owed := Decimal(P1.Value);
Owed := Owed + Amount;
Command.Parameters.Clear;
Command.CommandText := 'SELECT CREDIT INTO ? FROM CUSTOMER WHERE CUST_ID=?';
P1 := Command.Parameters.Add('P1', DbType.Decimal);
P2 := Command.Parameters.Add('P2', DbType.Int32);
P1.Direction := ParameterDirection.Output;
P2.Value := CustId;
Command.ExecuteNonQuery;
Credit := Decimal(P1.Value);
if Owed > Credit then
raise Exception.Create('Le client n'a pas suffisamment de crédit');
Command.Parameters.Clear;
Command.CommandText := 'UPDATE ITEMS SET STOCK=STOCK-? WHERE ITEM_ID=?';
P1 := Command.Parameters.Add('P1', DbType.Int32);
P2 := Command.Parameters.Add('P2', DbType.Int32);
P1.Value := Quantity;
P2.Value := ItemId;
Command.ExecuteNonQuery;
Command.Parameters.Clear;
Command.CommandText := 'INSERT INTO ORDERS (CUST_ID, ITEM_ID, QUANTITY, SALE_AMOUNT) '+ 'VALUES (?, ?, ?, ?)';
P1 := Command.Parameters.Add('P1', DbType.Int32);
P2 := Command.Parameters.Add('P2', DbType.Int32);
P3 := Command.Parameters.Add('P3', DbType.Int32);
P4 := Command.Parameters.Add('P4', DbType.Decimal);
P1.Value := CustId;
P2.Value := ItemId;
P3.Value := Quantity;
P4.Value := Amount;
Command.ExecuteNonQuery;
Command.Free;
end;
end.
Etape 2 : Construisez l'assemblage et rendez-le accessible au processus du serveur Blackfish SQL.
Après l'achèvement du code de la procédure stockée :
- Construisez une DLL d'assemblage (par exemple, Procs.dll) contenant la classe MyClass de l'étape 1.
- Lors du déploiement, copiez l'assemblage dans le sous-répertoire où réside l'exécutable du serveur Blackfish SQL (BSQLServer.exe).
Etape 3 : Créez la liaison entre un identificateur SQL et le membre de la classe.
Maintenant que le code est prêt pour l'exécution, la base de données Blackfish SQL doit être "avertie" de l'existence du membre de la classe appelable depuis SQL. Pour ce faire, démarrez DataExporer et exécutez la commande CREATE METHOD suivante :
CREATE METHOD ADD_ORDER AS 'MyProcs::SampleStoredProcedures.TMyClass.AddOrder';
MyProcs est le nom du package et le nom de la méthode est complet (nom de l'unité et nom de la classe).
Exécutez la procédure stockée ADD_ORDER depuis une application console Delphi :
unit MyCompany;
interface
implementation
uses
System.Data;
type
TSomething = class
public
procedure AddOrder(
Connection: DbConnection;
CustId: Integer;
ItemId: Integer;
Quantity: Integer);
end;
{ Assume:
Connection: est une connexion SQL Blackfish valide.
CustId: est un client de la table CUSTOMER.
ItemId: est un article de la table ITEMS.
Quantity: est la quantité commandée de cet article.
}
procedure TSomething.AddOrder(
Connection: DbConnection;
CustId: Integer;
ItemId: Integer;
Quantity: Integer);
var
Command: DbCommand;
P1, P2, P3: DbParameter;
begin
Command := con.CreateCommand;
Command.CommandText := 'ADD_ORDER';
Command.CommandType := CommandType.StoredProcedure;
P1 := Command.Parameters.Add('custId', DbType.Int32);
P2 := Command.Parameters.Add('itemId', DbType.Int32);
P3 := Command.Parameters.Add('quantity', DbType.Int32);
P1.Value := CustId;
P2.Value := ItemId;
P3.Value := Quantity;
Command.ExecuteNonQuery;
Command.Free;
end;
end.
Lorsque TSomeThing.AddOrder est appelée dans l'application client, la procédure stockée ADD_ORDER est appelée à son tour et cela entraîne l'exécution de TMyClass.AddOrder dans le processus du serveur Blackfish SQL. En plaçant TMyClass.AddOrder dans une procédure stockée, une seule instruction est exécutée via une connexion distante. Les cinq instructions exécutées par TMyClass.AddOrder le sont dans le processus du serveur Blackfish SQL, en utilisant une connexion locale.
Notez que l'application ne transmet pas l'instance d'une connexion à l'appel de la procédure stockée ADD_ORDER. Seuls les paramètres logiques réels sont transmis.
Blackfish SQL génère un objet de connexion implicite lorsqu'il trouve une procédure stockée, ou une FDU, dans laquelle le premier argument attendu est une instance de System.Data.IDbConnection.
Gestion des paramètres en sortie et des valeurs DBNull
La langage Delphi prend en charge les paramètres de sortie et les paramètres de référence. La base de données Blackfish SQL reconnaît ces types de paramètres et les traite en conséquence.
Les valeurs NULL de la base de données demandent une gestion spéciale. La System.String peut être gérée par la valeur NULL. Pour tous les autres types, cependant, le type du paramètre formel doit être modifié en TObject, puisque NULL n'est pas une valeur valide pour un ValueType .NET. Si le paramètre formel est de type TObject, la valeur de System.DBNull est utilisée pour une valeur NULL de la base de données. Blackfish SQL acceptera aussi des types nullables dans les procédures stockées écrites en C# (par exemple, int).
Exemples :
Exemple d'une procédure stockée avec un paramètre INOUT ; les valeurs NULL sont ignorées :
class procedure TMyClass.AddFive(ref Param: Integer); begin Param := Param + 5; end;
Exemple d'une procédure stockée avec un paramètre INOUT ; les valeurs NULL sont stockées en tant que valeurs NULL :
class procedure TMyClass.AddFour(ref Param: TObject);
begin
if Param <> nil then
Param := TObject(Integer(Param) + 4);
end;
Utilisation :
procedure TryAdding(Connection: DbConnection);
var
Command: DbCommand;
begin
Command := Connection.CreateCommand;
Command.CommandText := 'ADD_FIVE';
Command.CommandType := CommandType.StoredProcedure;
P1 := Command.Parameters.Add('param', DbType.Int32);
P1.Direction := ParameterDirection.InputOutput;
P1.Value = 17;
Command.ExecuteNonQuery;
if 22 <> Integer(P1.Value) then
raise Exception.Create('Résultat erroné');
Command.Parameters.Clear;
Command.CommandText := 'ADD_FOUR';
Command.CommandType := CommandType.StoredProcedure;
P1 := Command.Parameters.Add('param', DbType.Int32);
P1.Direction := ParameterDirection.InputOutput;
P1.Value = 17;
Command.ExecuteNonQuery;
if 21 <> Integer(P1.Value) then
raise Exception.Create('Résultat erroné');
P1.Value = DBNull.Value;
Command.ExecuteNonQuery;
if DbNull.Value <> P1.Value then
raise Exception.Create('Résultat erroné');
Command.Free;
end;
L'implémentation précédente de AddFour utilise une classe enveloppe TObject pour les entiers. Cela permet au développeur de addFour de reconnaître les valeurs NULL transmises par Blackfish SQL, et de définir par NULL un paramètre de sortie qui soit reconnu par Blackfish SQL.
Au contraire, dans l'implémentation de AddFive, il est impossible de savoir si un paramètre valait NULL, comme il est impossible de définir par NULL le résultat du paramètre de sortie.
Extension de SQL pour la base de données Blackfish SQL
Si un opérateur (par exemple, l'opérateur sur les bits AND) est nécessaire à une clause where pour une raison quelconque, et si Blackfish SQL ne dispose pas de cet opérateur, vous pouvez en créer un dans Delphi, Visual Basic, C# ou C++, et l'appeler en tant que FDU. Cependant, utilisez cette possibilité avec précaution car Blackfish SQL ne reconnaîtra pas l'objectif d'une telle fonction et ne pourra pas utiliser d'index pour accélérer cette partie de la requête.
Considérez l'exemple de FDU précédent, la FDU MAX_VALUE :
'SELECT * FROM PEOPLE WHERE MAX_VALUE(HEIGHT,5*WIDTH) < ?'
Cette requête est équivalente à celle qui suit :
'SELECT * FROM PEOPLE WHERE HEIGHT < ? AND 5*WIDTH < ?'
où la même valeur est donnée aux deux marqueurs de paramètres. Cette instruction SQL donne le même résultat, car l'implémentation de MAX_VALUE est connue. Cependant, Blackfish SQL ne pourra utiliser les index disponibles pour les colonnes HEIGHT et WIDTH que dans la seconde requête. S'il n'y avait pas ces index, les performances des deux requêtes seraient semblables. L'avantage d'écrire une FDU apparaît lorsque la fonctionnalité n'existe pas encore dans Blackfish SQL (par exemple, l'opérateur sur les bits AND).
Débogage des procédures stockées .NET
Pour déboguer les procédures stockées .NET :
- Lorsque le protocole est en-processus ou non défini
- Lorsque le protocole est TCP
Débogage des procédures stockées lorsque le protocole est en-processus ou non défini
Pour déboguer des procédures stockées lorsque le protocole est en-processus ou non défini :
- Créez le projet à utiliser pour le débogage. Dans votre EDI favori, créez un projet incluant le code client de l'application, les procédures stockées et une référence à la bibliothèque Borland.Data.BlackfishSQL.LocalClient.dll.
- Ajoutez des points d'arrêt dans la ou les procédures stockées. Le débogueur gérera les procédures stockées de la même manière que le code client.
Débogage des procédures stockées lorsque le protocole est TCP
Pour déboguer des procédures stockées lorsque le protocole est TCP
Si votre EDI prend en charge le débogage distant :
Delphi pourra s'attacher au processus du serveur Blackfish SQL.
- Compilez les procédures stockées avec les informations de débogage.
- Copiez l'assemblage dans le répertoire bin de l'installation de Blackfish SQL.
- Démarrez l'application client dans le débogueur et attachez-le au processus du serveur.
- Ajoutez des points d'arrêt dans la ou les procédures stockées. Le débogueur gérera les procédures stockées de la même manière que le code client.
Si votre EDI ne prend pas en charge le débogage distant :
- Créez le projet à utiliser pour le débogage. Configurez le projet pour déboguer le serveur directement.
- Créez un exécutable appelant Borland.Data.DataStore.DataStoreServer.StartDefaultServer.
- Ajoutez un point d'arrêt dans la procédure stockée.
- Exécutez le processus client distinct.
Utilisation d'une procédure stockée pour produire un IDataReader ADO.NET
Une procédure stockée peut produire un DbDataReader ADO.NET simplement en renvoyant un DbDataReader.
Exemple
class function GetRiskyCustomers(
Connection: DbConnection;
Credit: Decimal credit): DbDataReader;
var
Command: DbCommand;
P1: DbParameter;
begin
Command := Connection.CreateCommand;
Command.CommandText := 'SELECT NAME FROM CUSTOMER WHERE CREDIT > ? ';
P1 := Command.Parameters.Add('param', DbType.Decimal);
P1.Value := Credit;
Result := Command.ExecuteReader;
end;
Remarquez que l'objet command n'est pas libéré à la fin de la méthode. Si la commande était libérée, cela fermerait implicitement le DbDataReader et aucune donnée ne serait renvoyée par la procédure stockée. A la place, Blackfish SQL ferme la commande implicitement après que la procédure stockée a été appelée.
La procédure stockée GetRiskyCustomers peut être utilisée dans ADO de la manière suivante :
function GetRiskyCustomers(
Connection: DbConnection): ArrayList;
var
Command: DbCommand;
Reader: DbReader;
List: ArrayList;
begin
List := ArrayList.Create;
Command := Connection.CreateCommand;
Command.CommandText := 'GETRISKYCUST';
Command.CommandType := CommandType.StoredProcedure;
P1 := Command.Parameters.Add('Credit', DbType.Decimal);
P1.Value := 2000;
Reader := Command.ExecuteReader;
while Reader.Read do
List.Add(Reader.GetString(0));
Command.Free;
Result := List;
end;
Création de procédures stockées pour la plate-forme Java
Cette section détaille comment créer des procédures stockées et des FDU Blackfish SQL pour les plates-formes Java.
Création d'une procédure stockée pour une base de données Blackfish SQL
Les procédures stockées et les FDU pour Blackfish SQL pour Java doivent être écrites en Java. Les classes Java compilées des procédures stockées et des FDU doivent être ajoutées au CLASSPATH du processus du serveur Blackfish SQL pour être utilisées. Cela donne à l'administrateur de la base de données une chance de contrôler le code qui est ajouté. Seules les méthodes public static des classes public peuvent être utilisées.
Vous pouvez mettre à jour le chemin d'accès aux classes pour les outils de Blackfish SQL en ajoutant des classes au répertoire <home_jds>/lib/storedproc.
- Si la procédure stockée consiste en un fichier .jar, placez le fichier jar dans <home_jds>/storedproc/lib/jars.
- Si la procédure stockée consiste en un ou plusieurs fichiers de classes, placez les fichiers des classes dans <home_jds>/storedproc/classes. Par exemple, si votre fichier de procédure stockée est com.acme.MyProc, vous le placerez dans : c:<home_jds>/lib/storedproc/classes/com/acme/MyProc.class
Mise à la disposition du moteur SQL d'une procédure stockée ou d'une FDU
Une fois qu'une procédure stockée, ou qu'une FDU, a été écrite et ajoutée au CLASSPATH du processus du serveur Blackfish SQL, utilisez la syntaxe SQL suivante pour lui associer un nom de méthode :
CREATE JAVA_METHOD <nom-méthode> AS <chaîne-définition-méthode>
où <nom-méthode> est un identificateur SQL, comme INCREASE_SALARY, et <chaîne-définition-méthode> la chaîne du nom complet de la méthode. Par exemple :
com.mycompany.util.MyClass.increaseSalary
Les procédures stockées et les FDU peuvent être retirées de la base de données en exécutant :
DROP JAVA_METHOD <nom-méthode>
La méthode créée est prête à être utilisée. La section suivante explique comment définir et appeler une FDU.
Exemple de FDU
Cet exemple définit une méthode trouvant le premier caractère espace qui suit une certaine position dans une chaîne. Le premier snippet SQL définit la FDU, le second est un exemple de la manière de l'utiliser.
Supposez que TABLE1 contienne deux colonnes VARCHAR : FIRST_NAME et LAST_NAME. La fonction CHAR_LENGTH est une fonction SQL intégrée.
package com.mycompany.util;
public class MyClass {
public static int findNextSpace(String str, int start) {
return str.indexOf(' ',start);
}
}
CREATE JAVA_METHOD FIND_NEXT_SPACE AS
'com.mycompany.util.MyClass.findNextSpace';
SELECT * FROM TABLE1
WHERE FIND_NEXT_SPACE(FIRST_NAME, CHAR_LENGTH(LAST_NAME)) < 0;
Paramètres en entrée
Une dernière vérification du type des paramètres est effectuée quand la méthode Java est appelée. Les types numériques sont transtypés en un type supérieur afin de correspondre, si nécessaire, au type des paramètres d'une méthode Java. L'ordre des types numériques Java est :
- double ou Double
- float ou Float
- java.math.BigDecimal
- long ou Long
- int ou Integer
- short ou Short
- byte ou Byte
Les autres types Java reconnus sont :
- boolean ou Boolean
- String
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
- byte[]
- java.io.InputStream
Notez que, si vous passez des valeurs NULL à la méthode Java, vous ne pouvez pas utiliser de types primitifs comme short et double. Utilisez à la place les classes encapsulées équivalentes (Short, Double). Une valeur SQL NULL est transmise en tant que valeur Java null.
Si une méthode Java a un paramètre ou un tableau d'un type qui n'apparaît pas ci-dessus, il est géré comme le type SQL OBJECT.
Paramètres en sortie
Si le paramètre d'une méthode Java est un tableau d'un des types reconnus en entrée (sauf byte[]), il est considéré comme paramètre en sortie. Blackfish SQL transmet un tableau de longueur 1 (un) dans l'appel de la méthode, et la méthode est censée remplir le premier élément du tableau avec la valeur en sortie. Les types Java reconnus pour les paramètres en sortie sont :
- double[] ou Double[]
- float[] ou Float[]
- java.math.BigDecimal[]
- long[] ou Long[]
- int[] ou Integer[]
- short[] ou Short[]
- Byte[] (mais pas byte[], car il est reconnu en lui-même comme étant un paramètre en entrée)
- boolean[] ou Boolean[]
- String[]
- java.sql.Date[]
- java.sql.Time[]
- java.sql.Timestamp[]
- byte[][]
- java.io.InputStream[]
Les paramètres en sortie ne peuvent être liés qu'avec des marqueurs de variables en SQL. Tous les paramètres en sortie sont essentiellement des paramètres INOUT, car toute valeur définie avant l'exécution de l'instruction est transmise à la méthode Java. Si vous ne saisissez aucune valeur, la valeur initiale est arbitraire. Si l'un des paramètres peut renvoyer un NULL SQL (ou avoir une valeur correcte NULL en entrée), utilisez les classes encapsulées au lieu des types primitifs.
Exemple
package com.mycompany.util;
public class MyClass {
public static void max(int i1, int i2, int i3, int result[]) {
result[0] = Math.max(i1, Math.max(i2,i3));
}
}
CREATE JAVA_METHOD MAX
AS 'com.mycompany.util.MyClass.max';
CALL MAX(1,2,3,?);
L'instruction CALL doit être préparée par une instruction CallableStatement pour récupérer la valeur en sortie. Voir dans la documentation JDBC la façon d'utiliser java.sql.CallableStatement. Remarquez l'assignation de result[0] dans la méthode Java. Le tableau transmis à la méthode contient exactement un élément.
Paramètres de connexion implicites
Si le premier paramètre d'une méthode Java est de type java.sql.Connection, Blackfish SQL transmet un objet connexion qui partage le contexte de connexion transactionnel utilisé pour appeler la procédure stockée. Cet objet connexion peut servir à exécuter des instructions SQL en utilisant l'API JDBC.
Ne transmettez RIEN pour ce paramètre. Laissez Blackfish SQL le faire.
Exemple
package com.mycompany.util;
public class MyClass {
public static void increaseSalary(java.sql.Connection con,
java.math.BigDecimal amount) {
java.sql.PreparedStatement stmt
= con.prepareStatement("UPDATE EMPLOYEE SET SALARY=SALARY+?");
stmt.setBigDecimal(1,amount);
stmt.executeUpdate();
stmt.close();
}
}
CREATE JAVA_METHOD INCREASE_SALARY
AS 'com.mycompany.util.MyClass.increaseSalary';
CALL INCREASE_SALARY(20000.00);
Remarque :
- INCREASE_SALARY n'a besoin que d'un seul paramètre : la quantité dont il faut augmenter les salaires. La méthode Java correspondante a deux paramètres.
- N'appelez pas commit(), rollback(), setAutoCommit(), ni close() dans l'objet connexion transmis à la procédure stockée. Pour des raisons de performances, il n'est pas recommandé d'utiliser cette caractéristique pour une FDU, même si c'est possible.
Procédures stockées et ResultSet JDBC
Une procédure stockée Java peut produire un ResultSet sur le client en renvoyant soit un ResultSet, soit un DataSet DataExpress à partir de l'implémentation Java de la procédure stockée. Le DataSet est automatiquement converti en ResultSet pour l'utilisateur de la procédure stockée.
Exemple
L'exemple suivant renvoie un ResultSet :
package com.mycompany.util;
public class MyClass {
public static void getMarriedEmployees(java.sql.Connection con)
java.sql.Statement stmt = con.getStatement();
java.sql.ResultSet rset
= stmt.executeQuery("SELECT ID, NAME FROM EMPLOYEE
WHERE SPOUSE IS NOT NULL");
return rset;
}
Remarque : Ne fermez pas l'instruction stmt. Cette instruction est fermée implicitement.
Exemple
L'exemple suivant renvoie un DataSet, qui est automatiquement converti en ResultSet :
package com.mycompany.util;
public class MyClass {
public static void getMarriedEmployees()
com.borland.dx.dataset.DataSet dataSet = getDataSetFromSomeWhere();
return dataSet;
}
Remarque : Ne fermez pas l'instruction stmt. Cette instruction est fermée implicitement.
Exemple
Recensez et appelez les exemples précédents comme ceci :
java.sql.Statement stmt = connection.getStatement();
stmt.executeUpdate("CREATE JAVA_METHOD GET_MARRIED_EMPLOYEES AS "+
"'com.mycompany.util.MyClass.getMarriedEmployees'");
java.sql.ResultSet rset = stmt.executeQuery("CALL GET_MARRIED_EMPLOYEES()");
int id = rset.getInt(1);
String name = rset.getString(2);
Signatures de méthodes surchargées
Les méthodes Java peuvent être surchargées afin d'éviter toute perte de précision numérique.
Exemple
package com.mycompany.util;
public class MyClass {
public static int abs(int p) {
return Math.abs(p);
}
public static long abs(long p) {
return Math.abs(p);
}
public static BigDecimal abs(java.math.BigDecimal p) {
return p.abs();
}
public static double abs(double p) {
return Math.abs(p);
}
}
CREATE JAVA_METHOD ABS_NUMBER AS 'com.mycompany.util.MyClass.abs';
SELECT * FROM TABLE1 WHERE ABS(NUMBER1) = 2.1434;
La méthode surchargée abs est recensée une seule fois dans le moteur SQL. Maintenant, imaginez que la méthode abs attendant un BigDecimal n'ait pas été implémentée. Si NUMBER1 est un NUMERIC comportant des décimales, la méthode abs prenant un double sera appelée, ce qui représente une perte de précision potentielle lors de la conversion du nombre BigDecimal en double.
Mappage des types renvoyés
La valeur renvoyée par la méthode est mappée sur un type SQL équivalent. Voici le tableau de mappage des types :
| Type renvoyé par la méthode | Type SQL de Blackfish SQL |
|---|---|
|
byte ou Byte |
SMALLINT |
|
short ou Short |
SMALLINT |
|
int ou Integer |
INT |
|
long ou Long |
BIGINT |
|
java.math.BigDecimal |
DECIMAL |
|
float ou Float |
REAL |
|
double ou Double |
DOUBLE |
|
String |
VARCHAR |
|
boolean ou Boolean |
BOOLEAN |
|
java.io.InputStream (Tout type dérivé de java.io.InputStream est géré en tant que INPUTSTREAM) |
INPUTSTREAM |
|
java.sql.Date |
DATE |
|
java.sql.Time |
TIME |
|
java.sql.Timestamp |
TIMESTAMP |
|
Tous les autres types |
OBJECT |
Voir aussi
- Préface
- Présentation
- Architecture du système
- Etablissement des connexions
- Administration de Blackfish SQL
- Utilisation de la sécurité de Blackfish SQL
- Utilisation des déclencheurs dans les tables Blackfish SQL
- Référence des procédures stockées
- Référence SQL
- Optimisation des applications Blackfish SQL
- Déploiement des applications de bases de données Blackfish SQL
- Dépannage