blog.pagesd.info

Aller au contenu | Aller au menu | Aller à la recherche

mercredi 17 décembre 2008

Group By d'un champ Mémo sous Access

Hier soir j'ai enfin corrigé un bug sournois qui raccourcissait les descriptions des films à 255 caractères. Jusqu'à présent, je n'avais pas réussi à reproduire ce bug en local et donc à trouver ce qui pouvait le provoquer. Mais à force d'insister et d'éliminer tout ce qui ne pouvait pas poser problème, j'ai fini par avoir de gros doutes sur la requête qui sert à mettre à jour la date de dernière programmation des films.

Cette requête retrouve tous les films dont la date de dernière programmation actuellement enregistrée (dir_Movies.lastDate) est inférieure à la date de la dernière séance correspondant à ce film (dir_Seances.progDate).

SELECT T1.idMovie, 
       T1.displayName, 
       T1.description, 
       T1.length, 
       T1.picture, 
       T1.lastDate, 
       MAX(T2.progDate) AS progDate 
FROM   dir_Movies  T1, 
       dir_Seances T2 
WHERE  (T2.keyFilm = T1.idMovie) 
GROUP BY 
       T1.idMovie, 
       T1.displayName, 
       T1.description, 
       T1.length, 
       T1.picture, 
       T1.lastDate 
HAVING (T1.lastDate < MAX(T2.progDate))

Le souci, c'est qu'en local, cette requête ne renvoyait aucune ligne. Ce qui est "normal" dans la mesure où ma base de données locale est une simple copie de la base de données de production, et que lorsque je récupère cette copie, la mise à jour de la date de dernière programmation a déjà été faite.

Par conséquent, il a d'abord fallu bidouiller la table des films pour que je puisse tester en local cette requête. Pour cela, j'ai mis toutes les dates de dernière programmation au 1° décembre.

UPDATE dir_Movies SET dir_Movies.lastDate = #12/1/2008#;

Et là, la requête qui me semblait douteuse m'a renvoyé 52 lignes. Après avoir agrandi la colonne "description", j'ai pu constater qu'en effet celle-ci était bel et bien coupée et à première vue à quelque chose comme 255 caractères.

Etant donné que je n'avais pas vraiment besoin de faire un GROUP BY sur la description, j'ai donc modifié ma requête pour faire sortir la colonne "description" de la clause GROUP BY :

SELECT T1.idMovie, 
       T1.displayName, 
       T1.length, 
       T1.picture, 
       T1.lastDate, 
       MAX(T1.description) AS description, 
       MAX(T2.progDate) AS progDate 
FROM   dir_Movies  T1, 
       dir_Seances T2 
WHERE  (T2.keyFilm = T1.idMovie) 
GROUP BY 
       T1.idMovie, 
       T1.displayName, 
       T1.length, 
       T1.picture, 
       T1.lastDate 
HAVING (T1.lastDate < MAX(T2.progDate))

Malheureusement, Access n'a pas du tout apprécié et m'a gratifié du message d'erreur suivant : Impossible d'obtenir des champs Memo, OLE ou Hyperlink Object dans l'argument d'agrégat (T1.description).

Heureusement, Google a été plus conciliant et après quelques recherches j'ai fini par trouver qu'il suffisait d'utiliser la fonction FIRST() ou LAST() pour contourner le problème.

SELECT T1.idMovie, 
       T1.displayName, 
       T1.length, 
       T1.picture, 
       T1.lastDate, 
       LAST(T1.description) AS description, 
       MAX(T2.progDate) AS progDate 
FROM   dir_Movies  T1, 
       dir_Seances T2 
WHERE  (T2.keyFilm = T1.idMovie) 
GROUP BY 
       T1.idMovie, 
       T1.displayName, 
       T1.length, 
       T1.picture, 
       T1.lastDate 
HAVING (T1.lastDate < MAX(T2.progDate))

Et ça marche : la requête passe et la colonne description n'est pas tronquée à 255 caractères.

jeudi 13 novembre 2008

Installer le client ODBC pour Sybase SQL Anywhere 9

Pour mon super état des marges ultra prioritaire, je dois intégrer des données en provenance de la paye. Le problème c'est que le logiciel de paie utilise une base de données SQL Anywhere 9 et qu'il faut donc que je trouve comment m'y connecter. Et ben c'est pas si évident que ça pour trouver de l'information sur comment faire et encore moins pour arriver à récupérer un client pour Sql Anywhere 9 qui fasse l'affaire. Ou alors il faut être prêt à se tartiner des kilomètres de documentation et installer à tire larigot jusqu'à tomber sur le truc qui va bien.

Mais quand on a autant de temps que moi et qu'on ne veut pas encombrer son PC de tout un tas de trucs inutiles, il faut savoir se débrouiller (et aussi se contenter d'ODBC).

Pour commencer, il faut aller dans le dossier C:\Program Files\Sybase\SQL Anywhere 9\win32 d'une machine où SQL Anywhere 9 est déjà installé.

Une fois là, récupérer les 3 fichiers suivants :

  • dbodbc9.dll
  • dblgen9.dll
  • dbcon9.dll

Eventuellement, on peut aussi prendre les 2 fichiers suivants :

  • dblgfr9.dll : dblgen9.dll en français
  • dbcoen9.chm : fichier d'aide

Créer un dossier "C:\SQL Anywhere 9" et y copier les fichiers.

On dispose maintenant d'un répertoire contenant tous les fichiers nécessaires pour le bon fonctionnement du pilote ODBC de Sybase SQL Anywhere 9. Il reste simplement à configurer la base de registre pour qu'il soit possible de se connecter à Sybase via le pilote ODBC.

On continue et on lance regedit.exe pour ouvrir la base de registre

Aller dans HKEY_LOCAL_MACHINE \ SOFTWARE \ ODBC \ ODBCINST.INI. Là il faut se placer sur la clé "ODBC Drivers" et demander à y créer une nouvelle valeur chaine que l'on appellera "SQL Anywhere 9". Une fois cette valeur créée, double-cliquer dessus pour y enregistrer la valeur "Installed".

Rester dans HKEY_LOCAL_MACHINE \ SOFTWARE \ ODBC \ ODBCINST.INI et y créer une nouvelle clé "SQL Anywhere 9" (le même nom que la chaine créée auparavant). Se placer ensuite sur la clé que l'on vient de créer et ajouter les 2 valeurs chaines suivantes :

  • Driver
  • Setup

Puis pour chacune de ces deux chaines, enregistrer la valeur "C:\SQL Anywhere 9\dbodbc9.dll".

Ca y est, c'est quasiment fini.

On peut maintenant lancer l'administrateur de sources de données ODBC, cliquer sur le bouton "Ajouter" dans l'onglet "Sources de données système" et choisir le pilote "SQL Anywhere 9" pour obtenir la boite de dialogue permettant de configurer la connexion ODBC au serveur SQL Anywhere 9 :

odbc-sql-anywhere-9.png

A partir de là, il suffit de renseigner les différents informations qui vont bien, soit dans mon cas à peu près :

  • Onglet ODBC - Nom de source de données : BasePayeProd
  • Onglet ODBC - Description : Base de données Sybase de production pour la paie
  • Onglet Connexion - ID utilisateur : XXXXXX
  • Onglet Connexion - Mot de passe : XXXXXXXXX
  • Onglet Base de données - Nom du serveur : BasePayeProd
  • Onglet Réseau - TCP/IP : coché

Puis revenir sur l'onglet ODBC pour vérifier que tout est OK en cliquant sur le bouton "Tester la connexion".

Et quand on a comme moi on a la chance d'avoir un ODBCTST.EXE from Oracle, on peut immédiatement se connecter à la base de données pour vérifier que ça marche pour de vrai.

Ensuite, sous Visual Studio, on peut enfin se connecter à la base de donnée Sybase avec la commande suivante :

OdbcConnection db = new OdbcConnection("DSN=BasePayeProd");

mardi 22 juillet 2008

Select ... Not IN et autres bizarreries

Vite fait qui ne marche pas (0 résultat (???), 4 secondes) :

SELECT *
FROM   lux_ResourcesEntrys
WHERE  idResourcesEntry NOT IN (SELECT idEntry FROM lux_Extends)

Vite fait qui se traine (2874 résultats, 13 secondes) :

SELECT *
FROM   lux_ResourcesEntrys
MINUS
SELECT *
FROM   lux_ResourcesEntrys
WHERE  idResourcesEntry IN (SELECT idEntry FROM lux_Extends)

Bien fait (2874 résultats, 101 milli-secondes) :

SELECT T1.*
FROM   lux_ResourcesEntrys T1, lux_Extends T2
WHERE  T1.idResourcesEntry = T2.idEntry(+)
AND    T2.idEntry IS NULL
ORDER BY T1.idResourcesEntry DESC

mercredi 10 octobre 2007

Sql injection

{via monologue}

mercredi 30 mai 2007

Mise à jour d'une table à partir d'une autre

Pour mettre à jour un champ d'une table à partir du champ équivalent d'une autre table, Access accepte deux noms de tables pour la commande UPDATE, mais pas Sql Server.

Exemple : les taux de TVA ayant été corrigés dans la table des articles, il faut répercuter ces modifications dans la table des lignes de factures

Sous Access

UPDATE LignesFactures, Articles
SET    LignesFactures.TauxTva = Articles.TauxTva
WHERE  LignesFactures.ArticleID = Articles.ArticleID

Sous Sql Server

UPDATE LignesFactures
SET    LignesFactures.TauxTva = Articles.TauxTva
FROM   LignesFactures
INNER JOIN Articles ON Articles.ArticleID = LignesFactures.ArticleID

Mise à jour : Sous Oracle

UPDATE LignesFactures
SET    LignesFactures.TauxTva = (SELECT Articles.TauxTva
                                 FROM   Articles
                                 WHERE  Articles.ArticleID = LignesFactures.ArticleID)

vendredi 20 octobre 2006

Access 2000 et le Microsoft Jet SQL

Une liste d'articles intéressants sur MSDN à propos de l'utilisation du language SQL avec les bases de données Access 2000. A lire, imprimer et voir s'ils existe des trucs dans le même style pour les dernières versions d'Access.

Fundamental Microsoft Jet SQL for Access 2000

This article discusses the basic mechanics of using Jet SQL to work with data in an Access 2000 database. It also delves into using SQL to create and alter a database's structure. If you're new to manipulating data with SQL in an Access database, this article is a great place to start. (21 printed pages)

Intermediate Microsoft Jet SQL for Access 2000

Second in a series of three articles, Intermediate SQL builds on the concepts covered in the Fundamental SQL article and gives a much more detailed picture as to what can be accomplished with Microsoft Jet SQL in Access. For users and developers seeking to expand their understanding of Structured Query Language as it is used in the Microsoft Jet Database Engine, this article is designed to be the next logical step. (38 printed pages)

Advanced Microsoft Jet SQL for Access 2000

Third in a series of three articles, Advanced SQL builds on the concepts covered in the Fundamental and Intermediate articles, this time focusing on SQL syntax that is most often found in a multi-user environment. If you've read the previous two articles in an effort to become a well-rounded SQL user, this article will provide the final tools you will need to accomplish your goal. (24 printed pages)

Mise à jour :

jeudi 5 octobre 2006

Définition de données avec QC

Les "pseudo-types" de données de QC présentaient quels types de données utiliser avec QC.

Pour parvenir à ce résultat, on peut créer les tables dont on a besoin directement dans Access, TOAD, SQL Server Enterprise Manager… pour la base de données cible en veillant à bien respecter ces consignes.

Puis, lorsque le besoin d'utiliser une autre base de données se présente, il suffit de recréer les tables à l'identique dans l'autre base de données. Si on a été un peu prévoyant et que l'on dispose des scripts SQL de création de la base de données, il est possible de les modifier à coup de rechercher / remplacer pour les traduire de la syntaxe de la base de données source dans celle la base de données cible.

  • Avantage : on ne se complique pas la vie tant qu'on a pas besoin de changer de base de données.
  • Inconvénient : pas toujours évident d'avoir des scripts à jour (ou de pouvoir les regénérer) et le rechercher / remplacer ne fait pas tout.

Lorsqu'il est très probable que l'application devra être multi bases (ou lorsque la base de données cible n'est pas encore définie au début du projet), il est possible de rédiger les scripts de création de la structure de la base de données directement dans une syntaxe "multi-base".

L'outil de requêtes disponible avec QC supporte un certain nombre de commandes DDL (Data Definition Language) qui couvrent la majorité des cas rencontrés dans les scripts de création et de mise à jour des tables d'une base de données relationnelle.

Créer une table, sa clé primaire et un index

/* Create table
*/
CREATE TABLE test_Parametres (
  idParametre AUTOINCREMENT,
  libelle TEXT(100)
);
GO;

/* Create primary key
*/
ALTER TABLE test_Parametres
ADD CONSTRAINT PK_test_Parametres PRIMARY KEY (idParametre);
GO;

/* Create index
*/
CREATE UNIQUE INDEX UK_test_Parametres_libelle ON test_Parametres (libelle);
GO;

Créer une table, une clé étrangère et un index

/* Create table and primary key
*/
CREATE TABLE test_Donnees (
  idDonnee AUTOINCREMENT,
  vraiFaux BOOLEAN,
  petitEntier SMALLINT,
  entier INT,
  grandEntier BIGINT,
  simplePrecision SINGLE,
  doublePrecision DOUBLE,
  desSous CURRENCY,
  texteLong TEXT(2000),
  texteCourt TEXT(100),
  texteMemo MEMO,
  jourHeure DATETIME,
  idParametre INT,
  CONSTRAINT PK_test_Donnees PRIMARY KEY (idDonnee)
);
GO;

/* Create foreign key
*/
ALTER TABLE test_Donnees
ADD CONSTRAINT FK_test_Donnees_Parametres FOREIGN KEY (idParametre)
    REFERENCES test_Parametres (idParametre) ON DELETE CASCADE ON UPDATE CASCADE;
GO;

/* Create index
*/
CREATE INDEX IK_test_Donnees_texteCourt ON test_Donnees (texteCourt);
GO;

Notes :

  • dans ce cas, la création de la clé primaire a été définie au niveau de la commande CREATE TABLE.
  • ON UPDATE CASCADE n'est pas directement supporté avec Oracle

Modifier une table

/* Add a column
*/
ALTER TABLE test_Donnees ADD COLUMN autreChamp TEXT(50);
GO;

/* Modify a column
*/
ALTER TABLE test_Donnees MODIFY COLUMN autreChamp TEXT(100);
GO;

/* Rename a column
*/
ALTER TABLE test_Donnees RENAME COLUMN autreChamp TO autreTexte;
GO;

/* Remove a column
*/
ALTER TABLE test_Donnees DROP COLUMN autreTexte;
GO;

Note : RENAME COLUMN ne fonctionne pas avec Access et MySQL.

Faire du ménage

DROP TABLE test_Donnees;
GO;

DROP TABLE test_Parametres;
GO;

mercredi 27 septembre 2006

Les "pseudo-types" de données de QC

QC étant destiné à être multi base de données, il est nécessaire de prendre un certain nombre de précautions pour tout ce qui concerne SQL, qu'il s'agisse des requêtes ou des types de données.

Pour les requêtes on verra plus tard, pour les types de données, c'est ici.

Pour faciliter le développement multi base de données voire simplifier la migration d'une base de données à l'autre, QC ne gère qu'un sous-ensemble de types de données, qui fonctionnent de façon plus ou moins identique dans la plupart des bases de données.

La liste des "pseudo-types" de données reconnues par QC est la suivante :

  • AUTOINCREMENT
  • BOOLEAN
  • SMALLINT
  • INT
  • BIGINT
  • SINGLE
  • DOUBLE
  • CURRENCY
  • TEXT(2000)
  • TEXT
  • MEMO
  • DATETIME
  • DATE
  • TIME
  • BINDATA

Remarques :

  • Pour le type de données TEXT, il faut impérativement définir une longueur comprise entre 1 et 255 ou strictement égale à 2000.
  • Il est conseillé d'éviter d'utiliser des données de types CURRENCY (n'existe réellement que sous Access et Sql Server) et BINDATA.
  • Le type DATE et le type TIME ne doivent pas être utilisés. Ils sont uniquement destinés à gérer des tables déjà existantes pour lesquelles il serait impossible de modifier le type de données.

Transposition pour une base de données Access

  • AUTOINCREMENT : INT NOT NULL IDENTITY (1, 1)
  • BOOLEAN : BIT
  • SMALLINT : SMALLINT
  • INT : INTEGER
  • BIGINT : LONG
  • SINGLE : REAL
  • DOUBLE : DOUBLE PRECISION
  • CURRENCY : MONEY
  • TEXT(2000) : MEMO
  • TEXT : TEXT
  • MEMO : MEMO
  • DATETIME : DATETIME
  • DATE : DATE
  • TIME : TIME
  • BINDATA : IMAGE

Transposition pour une base de données Sql Server

  • AUTOINCREMENT : INT NOT NULL IDENTITY (1, 1)
  • BOOLEAN : BIT
  • SMALLINT : SMALLINT
  • INT : INTEGER
  • BIGINT : BIGINT
  • SINGLE : REAL
  • DOUBLE : DOUBLE PRECISION
  • CURRENCY : MONEY
  • TEXT(2000) : NVARCHAR(2000)
  • TEXT : NVARCHAR
  • MEMO : NTEXT
  • DATETIME : DATETIME
  • DATE : DATETIME
  • TIME : DATETIME
  • BINDATA : IMAGE

Transposition pour une base de données Oracle

  • AUTOINCREMENT : INT NOT NULL
  • BOOLEAN : NUMBER(1,0)
  • SMALLINT : NUMBER(5,0)
  • INT : NUMBER(10,0)
  • BIGINT : NUMBER(20,0)
  • SINGLE : FLOAT(24)
  • DOUBLE : FLOAT(48)
  • CURRENCY : NUMBER(19,1)
  • TEXT(2000) : VARCHAR2(2000)
  • TEXT : VARCHAR2
  • MEMO : CLOB
  • DATETIME : DATE
  • DATE : DATE
  • TIME : DATE
  • BINDATA : BLOB

Dans le cas du pseudo-type AUTOINCREMENT, l'incrémentation automatique est simulée à l'aide :

  • d'une séquence SEQ_NomTable,
  • d'un trigger before insert TRG_BI_NomTable

Transposition pour une base de données PostgreSQL

  • AUTOINCREMENT : BIGSERIAL
  • BOOLEAN : NUMERIC(1)
  • SMALLINT : INT2
  • INT : INT4
  • BIGINT : INT8
  • SINGLE : FLOAT4
  • DOUBLE : FLOAT8
  • CURRENCY : NUMERIC(16,4)
  • TEXT(2000) : VARCHAR(2000)
  • TEXT : VARCHAR
  • MEMO : TEXT
  • DATETIME : TIMESTAMP WITHOUT TIME ZONE
  • DATE : DATE
  • TIME : TIME
  • BINDATA : BYTEA

Transposition pour une base de données MySQL

  • AUTOINCREMENT : INT AUTO_INCREMENT
  • BOOLEAN : TINYINT(1)
  • SMALLINT : SMALLINT
  • INT : INTEGER
  • BIGINT : BIGINT
  • SINGLE : FLOAT
  • DOUBLE : DOUBLE PRECISION
  • CURRENCY : DECIMAL(16,4)
  • TEXT(2000) : TEXT
  • TEXT : VARCHAR
  • MEMO : MEDIUMTEXT
  • DATETIME : DATETIME
  • DATE : DATE
  • TIME : TIME
  • BINDATA : MEDIUMBLOB

Ecrire du code SQL portable

Quelques sites de référence pour ne plus coder du SQL tête baissée et prendre les bons réflexes de la portabilité :

dimanche 29 janvier 2006

Boite SqlRepeat

La boite SqlQuery automatise l'affichage du résultat d'une requête SQL dans une table à l'aide de l'objet XTable. La nouvelle boite SqlRepeat permet également d'afficher le résultat d'une requête SQL, mais offre plus de souplesse en ce qui concerne la présentation. Il est ainsi possible de définir :

  • le code html a afficher avant le résultat de la requête,
  • le code html servant de modèle pour formatter chaque ligne du résultat de la requête,
  • le code html à générer à la suite du résultat de la requête.

Exemple de paramétrage pour un fichier CSV :

  • Connection string : {odbc};Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=~/data/
  • Sql query :
    SELECT affix, givenName, legalName,
           telephone, email,
           addressLine1, postalCode, municipality
    FROM   [adresses.csv]
    ORDER BY postalCode DESC, legalName ASC, givenName ASC
    
  • Header section : <ol>
  • Template for each item : <h4>{0} {1} {2}</h4><ul><li>téléphone : {3}</li><li><a href='mailto:{4}'>{4}</a></li><li>{5} - {6} {7}</li></ul>
  • Footer section : </ol>

Dans le cas d'un fichier Excel, la paramétrage de la connexion et de la requête devraient être effectué de la façon suivante :

  • Connection string : {odbc};Driver={Microsoft Excel Driver (*.xls)};Dbq=~/data/adresses.xls
  • Sql query :
    SELECT affix, givenName, legalName,
           telephone, email,
           addressLine1, postalCode, municipality
    FROM   [Sheet1$]
    ORDER BY postalCode DESC, legalName ASC, givenName ASC
    

mardi 18 octobre 2005

Structure d'une table PostgreSQL depuis Information_Schema

SELECT COLUMN_NAME,
       DATA_TYPE,
       CHARACTER_MAXIMUM_LENGTH,
       NUMERIC_PRECISION,
       NUMERIC_SCALE,
       IS_NULLABLE,
       SUBSTR(COALESCE(COLUMN_DEFAULT, '' ), 1, 8 ) = 'nextval(' AS IS_AUTOINCREMENT,
       COLUMN_DEFAULT
FROM   INFORMATION_SCHEMA.COLUMNS
WHERE  TABLE_NAME = 'xxxxxxxx'
ORDER BY ORDINAL_POSITION

(publié à l'origine sur http://www.bigbold.com/snippets/posts/show/816)

Structure d'une table SQL Server depuis Information_Schema

SELECT COLUMN_NAME,
       DATA_TYPE,
       CHARACTER_MAXIMUM_LENGTH,
       NUMERIC_PRECISION,
       NUMERIC_SCALE,
       IS_NULLABLE,
       COLUMNPROPERTY(OBJECT_ID(TABLE_NAME), COLUMN_NAME, 'IsIdentity') AS IS_AUTOINCREMENT,
       COLUMN_DEFAULT
FROM   INFORMATION_SCHEMA.COLUMNS
WHERE  TABLE_NAME = 'xxxxxxxx'
ORDER BY ORDINAL_POSITION

(publié à l'origine sur http://www.bigbold.com/snippets/posts/show/815)

Edit : Voir aussi "system_function_schema.fn_datadictionary", une fonction qui renvoie le dictionnaire de données pour n'importe quelle base Sql Server.

mardi 20 septembre 2005

Définir une valeur Identity sous Sql Server

SET IDENTITY_INSERT MyTable ON;
INSERT INTO MyTable
    (MyIdentityField, MyFirstField, MySecondField)
VALUES
    (12345, 'ABCDE', 'etc...');
SET IDENTITY_INSERT MyTable OFF;

(publié à l'origine sur http://www.bigbold.com/snippets/posts/show/755)

Literal DateTime pour SQL Server

CONVERT(DATETIME, 'yyyymmdd', 112)

112 -> ISO date cf. CAST and CONVERT

Edit : une bien meilleure solution de Wild Richard :

{d 'yyyy-mm-dd'}

(publié à l'origine sur http://www.bigbold.com/snippets/posts/show/754)

jeudi 23 juin 2005

(Wdevs) Another MySQL manager

EMS offers a free lite version of MySQL Manager. And they distribute PostgreSQL Manager Lite, MS SQL Manager Lite and Firebird Manager Lite for free too.

lundi 21 mars 2005

(Wdevs) Oracle, auto-increment column and pre-defined values

This week-end, I looked for a way to have auto-increment column in Oracle while having the possibility to set a given value in some inserts.

Several years ago, I used a trigger where the pseudo auto-incremented column was initialized with a sequence only when its value is empty.

CREATE OR REPLACE TRIGGER TRG_BI_all_Increments
   BEFORE INSERT
   ON all_Increments
   FOR EACH ROW
BEGIN
   IF (:NEW.ID IS NULL) THEN
      SELECT SEQ_all_Increments.NEXTVAL INTO :NEW.ID FROM DUAL;
   END IF;
END;

That enabled me to initialize parameters tables with default values from an sql script. The drawback was that once the data are loaded, the start value for the sequence had to be manually reset to the maxim value inserted in order to avoid duplicate errors.

I rewrote it so that when an INSERT statement define the ID value, the triggeer checks if this value is greather than the current sequence value and in this case automatically reset the sequence to the inserted value.

/* create table */
CREATE TABLE all_Increments (
    id   INT NOT NULL ,
    test VARCHAR2(100) ,
    CONSTRAINT PK_all_Increments
    PRIMARY KEY ( id )
);

/* create sequence */
CREATE SEQUENCE SEQ_all_Increments
    START WITH 1
    MAXVALUE 1.0E28
    MINVALUE 1
    NOCYCLE
    NOCACHE
    ORDER;

/* create trigger */
CREATE OR REPLACE TRIGGER TRG_BI_all_Increments
    BEFORE INSERT
    ON all_Increments
    FOR EACH ROW
DECLARE
    last_Sequence NUMBER;
    last_InsertID NUMBER;
BEGIN
    IF (:NEW.id IS NULL) THEN
         SELECT SEQ_all_Increments.NEXTVAL INTO :NEW.id FROM DUAL;
    ELSE
         SELECT NVL(Last_Number, 0) INTO last_Sequence
           FROM User_Sequences
          WHERE UPPER(Sequence_Name) = UPPER('SEQ_all_Increments');
         SELECT :NEW.id INTO last_InsertID FROM DUAL;
         WHILE (last_InsertID > last_Sequence) LOOP
              SELECT SEQ_all_Increments.NEXTVAL INTO last_Sequence FROM DUAL;
         END LOOP;
    END IF;
END;

/* test values */
INSERT INTO all_Increments (id, test) values (1, 'one');
INSERT INTO all_Increments (id, test) values (2, 'two');
INSERT INTO all_Increments (id, test) values (3, 'three');
INSERT INTO all_Increments (id, test) values (10, 'ten');
INSERT INTO all_Increments (test) values ('eleven?');
INSERT INTO all_Increments (id, test) values (5, 'five?');
INSERT INTO all_Increments (test) values ('twelve?');

lundi 17 janvier 2005

(Wdevs) TOAD for MySQL

Quest Software has released TOAD for MySQL. That would be great if they succeeded to make it as good as TOAD for Oracle. Currently, I was using trying to use MySQL-Front, but it drives me crazy.

They offer TOAD for MySQL as a freeware release. The only drawback is that every 60 days it's necessary to download and install it again. And as there is a TOAD for SQL Server too I will have to work again at the MSDE version of my portal.