Professional Documents
Culture Documents
SQL Practica
SQL Practica
SELECT
INSERT
DELETE
UPDATE
CREATE TABEL
DROP TABLE
ALTER TABLE
CREATE VIEW
CREATE CURSOR
ROLLBACK
DEFAULT 10 ;
CHECK (OrderQty > 9) ;
ERROR "Order Quantity must be at least 10", ;
DiscPercent n(6,2) NULL ;
DEFAULT .NULL., ;
CHECK (OrderAmt > 0) ERROR "Order Amount Must be > 0" )
* Display new database, tables, and relationships
MODIFY DATABASE
* Delete example files
SET SAFETY OFF && To suppress verification message
CLOSE DATABASES
&& Close database before deleting
DELETE DATABASE mydata1 DELETETABLES
PRIMARY KEY;
CHECK(cospost=LTRIM(UPPER(codpost)));
ERROR 'Codul postal se scrie fara spatii la inceput !', ;
loc CHAT(25) ;
NOT NULL ;
CHECK(loc=LTRIM(PROPER(loc))) ;
ERROR 'Prima literea din fiecare cuvint al' + CHR (13)+;
'denumirii localitatii este majuscula'+ CHR (13)+;
'restul literelor sint mici !',;
nrai CHAR(2);
DEFAULT 'IS',;
FOREIGN KEY nrai TAG nrai REFERENCES raioane TAG nrai;
);
********** Tabelul 3
CREATE TABLE clienti (;
codcl NUMBER(6);
PRIMARY KEY;
CHECK(codcl>1000),;
ERROR 'Codul clientului trebuie sa fie mai mare decit 1000 !', ;
dencl CHAR(30) ;
CHECK(SUBSTR(dencl,1,1)=UPPER(SUBSTR(dencl,1,1))) ;
ERROR 'Prima literea din denumirea clientului este'+ CHR (13)+;
'obligatoriu majuscula!' ,;
codfiscal CHAR(9);
NULL,;
CHECK(SUBSTR(codfiscal,1,1)=UPPER(SUBSTR(codfiscal,1,1))) ;
ERROR 'Prima literea din codul fiscal este'+ CHR (13)+;
'obligatoriu majuscula!' ,;
adresa CHAR(40);
NULL;
CHECK(SUBSTR(adresa,1,1)=UPPER(SUBSTR(adresa,1,1))) ;
ERROR 'Prima literea din adresa este'+ CHR (13)+;
'obligatoriu majuscula!' ,;
codpost CHAR(5),;
telefon CHAR(10) ;
NULL, ;
FOREIGN KEY codpost TAG codpost REFERENCES localitati TAG codpost;
);
********** Tabelul 4
CREATE TABLE persoane (;
cnp CHAR(14);
PRIMARY KEY;
CHECK(cnp=LTRIM(UPPER(cnp)));
ERROR 'Codul postal se scrie fara spatii la inceput !', ;
nume CHAR(20) ;
CHECK(nume= LTRIM(PROPER(nume))) ;
ERROR 'Prima literea din fiecare cuvint al' + CHR (13)+;
'numelui persoanei este majuscula'+ CHR (13)+;
'restul literelor sint mici !',;
prenume CHAR(20);
CHECK(prenume= LTRIM(PROPER(prenume))) ;
4
datainc DATE;
DEFAULT DATE();
CHECK(BETWEEN(datainc,{^2001/01/01},{^2010/12/31})) ;
ERROR 'Data inc se afal in interv 1 ian 2001-31 decembrie 2010!', ;
coddoc CHAR(4);
CHECK(coddoc= UPPER (LTRIM (coddoc)));
ERROR 'Codul documentului se scrie cu majuscule!', ;
nrdoc CHAR(16),;
datadoc DATE;
DEFAULT DATE()-5;
)
********** Tabelul 11
CREATE TABLE incasfact(;
codinc NUMBER(8),;
nrfact NUMBER(8),;
transa NUMBER(16) NOT NULL,;
PRIMARY KEY STR(codinc,8)+STR(nrfact,8) TAG primaru, ;
FOREIGN KEY codinc TAG codinc REFERENCES incasari TAG codinc,;
FOREIGN KEY nrfact TAG nrfact REFERENCES facturi TAG nrfact;
)
Atentie!!!
La crearea indexilor compusi, la crearea indexilor Primari / PRIMARY KEY /, Regulari /FOREIGN
KEY/ si Candidat /UNOQUE/.
Din pacate declararea cheilor straine nu inseamna si intituirea restrictiei referentiale. Pentru a o institui
este necesar de a institui restrictiile mentionate cu Referential Integrity Builder.
3. MODIFICAREA STRUCTURII TABELELOR
O proiectare buna in general creaza putine probleme ce tin de modificarea structurii BD. Ea de fapt
ramine intacta. Cu toate acestea pot aparea unele necesitati de modificare a lungimii unui atribut,
adaugarii unui atribut, stergerii unui atribut s.a.
Pentru a modifica structura tabelelor de date este utilizata comanda ALTER TABLE. In cele ce urmeaza
vom prezenta citeva formate de sintaxa a acestei comenzi si citeva exemple.
ALTER TABLE TableName1
ADD | ALTER [COLUMN] FieldName1
FieldType [(nFieldWidth [, nPrecision])]
[NULL | NOT NULL]
[CHECK lExpression1 [ERROR cMessageText1]]
[DEFAULT eExpression1]
[PRIMARY KEY | UNIQUE]
[REFERENCES TableName2 [TAG TagName1]]
[NOCPTRANS]
[NOVALIDATE]
-orALTER TABLE TableName1
ALTER [COLUMN] FieldName2
[NULL | NOT NULL]
[SET DEFAULT eExpression2]
[SET CHECK lExpression2 [ERROR cMessageText2]]
[DROP DEFAULT]
7
[DROP CHECK]
[NOVALIDATE]
-orALTER TABLE TableName1
[DROP [COLUMN] FieldName3]
[SET CHECK lExpression3 [ERROR cMessageText3]]
[DROP CHECK]
[ADD PRIMARY KEY eExpression3 TAG TagName2 [FOR lExpression4]]
[DROP PRIMARY KEY]
[ADD UNIQUE eExpression4 [TAG TagName3 [FOR lExpression5]]]
[DROP UNIQUE TAG TagName4]
[ADD FOREIGN KEY [eExpression5] TAG TagName4 [FOR lExpression6]
REFERENCES TableName2 [TAG TagName5]]
[DROP FOREIGN KEY TAG TagName6 [SAVE]]
[RENAME COLUMN FieldName4 TO FieldName5]
[NOVALIDATE]
Exemple din HELP VFP.
ALTER TABLE SQL Command Examples
Example 1 adds a field called fax to the customer table and allows the field to have null values.
Example 2 makes the cust_id field the primary key of the customer table.
Example 3 adds a field validation rule to the quantity field of the orders table so that values in the
quantity field must be non-negative.
Example 4 adds a one-to-many persistent relation between the customer and orders tables based on
the primary key cust_id in the customer table and a new foreign key index cust_id in the orders
table.
Example 5 removes the field validation rule from the quantity field in the orders table.
Example 6 removes the persistent relation between the customer and orders tables, but keeps the
cust_id index tag in the orders table.
Example 7 adds a field called fax2 to the customer table and prevents the field from containing null
values. The new structure of the table is displayed. Two ALTER COLUMN clauses are used to allow the
field to have null values and set the default value for the field to the null value. Note that multiple
ALTER COLUMN clauses are required to change more than one property of a field in a single ALTER
TABLE command. The new field is then removed from the table to restore the table to its original state.
* Example 1
SET PATH TO (HOME(2) + 'Data\')
&& Sets path to table
ALTER TABLE customer ADD COLUMN fax c(20) NULL
* Example 2
ALTER TABLE customer ADD PRIMARY KEY cust_id TAG cust_id
ALTER TABLE customer ALTER COLUMN cust_id c(5) PRIMARY KEY
* Example 3
ALTER TABLE orders;
ALTER COLUMN quantity SET CHECK quantity >= 0;
ERROR "Quantities must be non-negative"
* Example 4
ALTER TABLE orders;
ADD FOREIGN KEY cust_id TAG cust_id REFERENCES customer
* Example 5
ALTER TABLE PERSOANE ADD PRIMARY KEY (CNP) && numele cimpului in paranteze
Atentie!!!
NOVALIDATE se permite operarea unor modificari ale structurii chiar daca acestea
ar viola integritatea datelor.
4.COMENZI DE ACTUALIZARE
Trei sunt comenzile de actualizare INSERT, UPDATE si DELETE
A. Adaugarea unei linii/inscrieri
Din HELP al VFP
Appends a record to the end of a table that contains the specified field values.
Syntaxa
INSERT INTO dbf_name [(fname1 [, fname2, ...])]
VALUES (eExpression1 [, eExpression2, ...])
-orINSERT INTO dbf_name FROM ARRAY ArrayName | FROM MEMVAR
Arguments
INSERT INTO dbf_name
Specifies the name of the table to which the new record is appended. dbf_name can include a path and
can be a name expression.
If the table you specify isn't open, it is opened exclusively in a new work area and the new record is
appended to the table. The new work area isn't selected; the current work area remains selected.
If the table you specify is open, INSERT appends the new record to the table. If the table is open in a
work area other than the current work area, it isn't selected after the record is appended; the current
work area remains selected.
[(fname1 [, fname2 [, ...]])]
Specifies the names of the fields in the new record into which the values are inserted.
VALUES (eExpression1 [, eExpression2 [, ...]])
Specifies the field values inserted into the new record. If you omit the field names, you must specify the
field values in the order defined by the table structure. If SET NULL is ON, INSERT SQL attempts to
insert null values into any fields not specified in the VALUES clause.
FROM ARRAY ArrayName
Specifies the array whose data is inserted into the new record. The contents of the elements of the array,
starting with the first element, are inserted into the corresponding fields of the record. The contents of
the first array element are inserted into the first field of the new record; the contents of the second array
element are inserted into the second field, and so on.
Any default values for fields are ignored when you include the FROM ARRAY clause.
FROM MEMVAR
Specifies that the contents of variables are inserted into fields with the same names as the variables. If a
variable doesn't exist with the same name as the field, the field is left empty.
Remarks
The new record contains the data listed in the VALUES clause or contained in the specified array or
variables. The record pointer is positioned on the new record.
INSERT SQL Command Examples din HELP VFP
10
The following example opens the employee table and adds one record.
USE employee
INSERT INTO employee (emp_no, fname, lname, officeno) ;
VALUES (3022, "John", "Smith", 2101)
The following example opens the customer table in the testdata database.
Atentie!!!
Ordinea valorilor in clauza VALUES trebuie sa fie identica cu cea declarata la
crearea (sau modificarea structurii) tabelelor. Modificarea este posibila numai
prin enumararea dupa numele tabelei, a atributelor ce vor primi valorile
specificate
B. STERGEREA UNOR LINII/INSCRIERI
Din HELP VFP
Marks records for deletion.
Syntax
DELETE
[Scope] [FOR lExpression1] [WHILE lExpression2]
[IN nWorkArea | cTableAlias]
[NOOPTIMIZE]
Arguments
Scope
Specifies a range of records to mark for deletion. The scope clauses are: ALL, NEXT nRecords,
RECORD nRecordNumber, and REST.
The default scope for DELETE is the current record (NEXT 1).
FOR lExpression1
Specifies a condition whereby only the records that satisfy the logical condition lExpression1 are
marked for deletion.
11
Rushmore optimizes a query created with DELETE ... FOR if lExpression1 is an optimizable expression
and the table is indexed on DELETED( ). For best performance, use an optimizable expression in the
FOR clause.
WHILE lExpression2
Specifies a condition whereby records are marked for deletion for as long as lExpression2 evaluates to
true (.T.).
IN nWorkArea
Specifies the work area of the table in which records are marked for deletion.
IN cTableAlias
Specifies the alias of the table in which records are marked for deletion.
If you omit nWorkArea and cTableAlias, records are marked for deletion in the table in the currently
selected work area.
NOOPTIMIZE
Disables Rushmore optimization of DELETE.
Remarks
Records marked for deletion aren't physically removed from the table until PACK is issued. Records
marked for deletion can be recalled (unmarked) with RECALL.
DELETE Command Example din HELP VFP
The following example opens the customer table in the testdata database. DELETE is used to mark
all records for deletion where the country field contains USA. All the records marked for deletion are
displayed. RECALL ALL is used to unmark all the records marked for deletion.
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'Data\testdata')
USE customer && Opens Customer table
DELETE FOR country = 'USA' && Mark for deletion
CLEAR
LIST FIELDS company, country FOR DELETED( ) && List marked records
RECALL ALL && Unmark all records marked for deletion
12
*********Inserare de date
INSERT INTO raioane VALUES (AN,Anenii Noi, Centru)
INSERT INTO raioane VALUES (ST,Straseni, Centru)
INSERT INTO raioane VALUES (CR,Criuleni, Centru)
INSERT INTO raioane VALUES (IA,Ialoveni, Centru)
INSERT INTO raioane VALUES (HI,Hincesti, Centru)
INSERT INTO raioane VALUES (NI,Nisporeni, Centru)
INSERT INTO raioane VALUES (SO,Soroca, Nord)
INSERT INTO raioane VALUES (ED,Edinet, Nord)
INSERT INTO raioane VALUES (BR,Briceni, Nord)
INSERT INTO raioane VALUES (RE,Rezina, Nord)
INSERT INTO raioane VALUES (CH,Cahul, Sud)
INSERT INTO raioane VALUES (CA,Cantemir, Sud)
INSERT INTO raioane VALUES (LE,Leova, Sud)
INSERT INTO raioane VALUES (GA,UTAG, Sud)
INSERT INTO localitati VALUES (2200,Anenii Noi, AN)
INSERT INTO localitati VALUES (2300,Anenii Noi, AN)
INSERT INTO localitati VALUES (2000,Straseni, ST)
INSERT INTO localitati VALUES (2100,Straseni, ST)
INSERT INTO localitati VALUES (2400,Criuleni, CR)
INSERT INTO localitati VALUES (2500,Criuleni, CR)
INSERT INTO localitati VALUES (2600,Cantemir, CA)
INSERT INTO localitati VALUES (2700,Ialoveni, IA)
INSERT INTO localitati VALUES (3000,Hincesti, HI)
INSERT INTO localitati VALUES (3200,Hincesti, HI)
INSERT INTO localitati VALUES (3400,Edinet, ED)
INSERT INTO localitati VALUES (3600,Cahul, CH)
INSERT INTO clienti VALUES (1001,Client 1 SRL,R1001,Cucima 13,2000,NULL)
INSERT INTO clienti (codcl,dencl,codfiscal,codpost,telefon);
VALUES (1002,Client 2 SRL,R1002,Cucima 13,2700,032-212121)
INSERT INTO clienti VALUES (1003,Client 1 SRL,R1003,Putin 13,2200,NULL)
INSERT INTO clienti (codcl,dencl,codfiscal,codpost,telefon);
VALUES (1004,Client 2 SRL,R1004,Cucima 13,2200,032-212121)
INSERT INTO clienti VALUES (1005,Client 1 SRL,R1005,Brejnev 13,2000,NULL)
INSERT INTO clienti VALUES (1006,Client 1 SRL,R1006,Ustinov 13,2200,NULL)
INSERT INTO clienti VALUES (1007,Client 1 SRL,R1007,Andropov 13,3400,NULL)
INSERT INTO clienti VALUES (1008,Client 1 SRL,R1008,Cosighin 13,2200,NULL)
INSERT INTO persoane
VALUES (CNP1,Ion, Vasile,Sloboda 13,B,2200,123456,987654,094222222,NULL)
INSERT INTO persoane
13
VALUES(\ (1112,{^2001/08/01},001,1001)
INSERT INTO facturi (nrfact,datafact,gestiune,codcl)
VALUES(\ (1113,{^2001/08/01},001,1002)
INSERT INTO facturi (nrfact,datafact,gestiune,codcl)
VALUES(\ (1114,{^2001/08/01},001,1002)
INSERT INTO facturi (nrfact,datafact,gestiune,codcl)
VALUES(\ (1115,{^2001/08/01},001,1003)
INSERT INTO facturi (nrfact,datafact,gestiune,codcl)
VALUES(\ (1116,{^2001/08/01},001,1003)
INSERT INTO facturi (nrfact,datafact,gestiune,codcl)
VALUES(\ (1117,{^2001/08/01},001,1004)
INSERT INTO liniifact VALUES(\ (1111,1,1,50,10000)
INSERT INTO liniifact VALUES(\ (1111,2,2,75,10500)
INSERT INTO liniifact VALUES(\ (1111,3,5,500,6500)
INSERT INTO liniifact VALUES(\ (1112,1,2,80,10300)
INSERT INTO liniifact VALUES(\ (1112,2,3,40,7500)
INSERT INTO liniifact VALUES(\ (1113,1,2,100,9750)
INSERT INTO liniifact VALUES(\ (1113,1,2,70,10700)
INSERT INTO liniifact VALUES(\ (1113,2,4,30,15800)
INSERT INTO liniifact VALUES(\ (1114,3,5,700,10000)
INSERT INTO liniifact VALUES(\ (1114,1,2,150,9300)
INSERT INTO liniifact VALUES(\ (1114,1,2,125,9300)
INSERT INTO liniifact VALUES(\ (1115,1,2,100,9500)
INSERT INTO liniifact VALUES(\ (1116,2,1,150,6400)
INSERT INTO liniifact VALUES(\ (1117,1,2,35,10500)
INSERT INTO incasari VALUES(\ (1234,{^2001/08/15},OP,111,{^2000/08/10})
INSERT INTO incasari VALUES(\ (1235,{^2001/08/15},CHIT,222,{^2000/08/15})
INSERT INTO incasari VALUES(\ (1236,{^2001/08/16},OP,333,{^2000/08/09})
INSERT INTO incasari VALUES(\ (1237,{^2001/08/17},CEC,444,{^2000/08/10})
INSERT INTO incasari VALUES(\ (1238,{^2001/08/17},OP,555,{^2000/08/10})
INSERT INTO incasari VALUES(\ (1239,{^2001/08/18},OP,666,{^2000/08/11})
INSERT INTO incasfact VALUES(\ (1234,1111,5399625)
INSERT INTO incasfact VALUES(\ (1234,1118,5399625)
INSERT INTO incasfact VALUES(\ (1235,1112,5399625)
INSERT INTO incasfact VALUES(\ (1235,1117,5399625)
INSERT INTO incasfact VALUES(\ (1236,1118,5399625)
INSERT INTO incasfact VALUES(\ (1236,1120,5399625)
INSERT INTO incasfact VALUES(\ (1237,1117,5399625)
INSERT INTO incasfact VALUES(\ (1238,1113,5399625)
INSERT INTO incasfact VALUES(\ (1239,1117,5399625)
Atentie!!!
In exemplul de mai sus am pornit de la presupunerea ca in directoriul current exista cite un fisier graphic
cu extensia tif pentru fiecare produs, iar ordinea acestora coiencide cu ordinea produselor din tabela,
ceea ce e destul de riscant. Astfel incit procedura ce urmeaza pare a fi una mai adecvata.
SELECT PRODUSE
15
SCAN
Nume_=figura_+LTRIM(STR(codpr,6))+.TIF
IF FILE((nume_))
APPEND GENERAL image FROM (nume_) LINK
ENDIF
ENDSCAN
C. MODIFICAREA VALORILOR UNOR ATTRIBUTE
Updates records in a table with new values.
Syntax
UPDATE [DatabaseName1!]TableName1
SET Column_Name1 = eExpression1
[, Column_Name2 = eExpression2 ...]
WHERE FilterCondition1 [AND | OR FilterCondition2 ...]]
Arguments
[DatabaseName1!]TableName1
Specifies the table in which records are updated with new values.
DatabaseName1! specifies the name of a non-current database containing the table. You must include
the name of the database containing the table if the database is not the current one. Include the
exclamation point (!) delimiter after the database name and before the table name.
SET Column_Name1 = eExpression1
[, Column_Name2 = eExpression2
Specifies the columns that are updated and their new values. If you omit the WHERE clause, every row
in the column is updated with the same value.
WHERE FilterCondition1 [AND | OR FilterCondition2 ...]]
Specifies the records that are updated with new values.
FilterCondition specifies the criteria that records must meet to be updated with new values. You can
include as many filter conditions as you like, connecting them with the AND or OR operator. You can
also use the NOT operator to reverse the value of a logical expression, or use EMPTY( ) to check for an
empty field.
Remarks
UPDATE - SQL can only update records in a single table. Note that subqueries are supported in
UPDATE SQL.
Unlike REPLACE, UPDATE - SQL uses record locking when updating multiple records in a table
opened for shared access. This reduces record contention in multiuser situations, but may reduce
performance. For maximum performance, open the table for exclusive use or use FLOCK( ) to lock the
table.
UPDATE - SQL Command Example din HELP VFP
The following example opens the customer table in the testdata database. UPDATE -SQL is used to
set all of the values in the maxordamt field to 25.
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'Data\testdata')
USE Customer
&& Open customer table
* Set and display amounts for customers
UPDATE customer SET maxordamt = 25
16
Example 1 displays the names of all companies in customer (one field from one table).
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT customer.company ;
FROM customer
Example 2
Example 2 displays the contents of three fields from two tables and joins the two tables based on the
cust_id field. It uses local aliases for both tables.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT a.company, b.order_date, b.shipped_on ;
FROM customer a, orders b ;
WHERE a.cust_id = b.cust_id
Example 3
Example 3 displays only records with unique data in the specified fields.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT DISTINCT a.company, b.order_date, b.shipped_on ;
FROM customer a, orders b ;
WHERE a.cust_id = b.cust_id
Example 4
Example 4 displays the country, postalcode, and company fields in ascending order.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT country, postalcode, company ;
FROM customer ;
ORDER BY country, postalcode, company
Example 5
Example 5 stores the contents of fields from two tables in a third table.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT a.company, b.order_date, b.shipped_on ;
FROM customer a, orders b ;
WHERE a.cust_id = b.cust_id ;
INTO TABLE custship.dbf
BROWSE
Example 6
Example 6 displays only records with an order date earlier than 02/16/1994.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT a.company, b.order_date, b.shipped_on ;
FROM customer a, orders b ;
WHERE a.cust_id = b.cust_id ;
AND b.order_date < {^1994-02-16}
Example 7
Example 7 displays the names of all companies from customer with a postal code that matches a postal
code in the orders table.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT company FROM customer a WHERE ;
EXISTS (SELECT * FROM orders b WHERE a.postalcode = b.postalcode)
Example 8
18
Example 8 displays all records from customer having a company name that begins with an uppercase C
and is an unknown length.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT * FROM customer a WHERE a.company LIKE "C%"
Example 9
Example 9 displays all records from customer having a country name that begins with an uppercase U
and is followed by one unknown character.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT * FROM customer a WHERE a.country LIKE "U_"
Example 10
Example 10 displays the names of all cities in customer in uppercase and names the output column
CityList.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT UPPER(city) AS CityList FROM customer
Example 11
Example 11 demonstrates how you can perform a query on data that contains percentage signs (%). A
backslash (\) is placed before the percentage sign to indicate that it should be treated as a literal, and the
backslash is specified as the escape character in the ESCAPE clause.
Because the sample tables included with Visual FoxPro do not contain the percentage sign character, this
query returns no results.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT * FROM customer;
WHERE company LIKE "%\%%" ESCAPE "\"
Example 12
Example 12 demonstrates how you can perform a query on data that contains underscores (_). A
backslash (\) is placed before the underscore to indicate that it should be treated as a literal, and the
backslash is specified as the escape character in the ESCAPE clause.
Because the sample tables included with Visual FoxPro do not contain the underscore character, this
query returns no results.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT * FROM customer;
WHERE company LIKE "%\_%" ESCAPE "\"
Example 13
In example 13, the Escape character uses itself as a literal. The dash is both the escape character and a
literal. The query returns all rows where the company name contains a percentage sign followed by a
dash.
Because the sample tables included with Visual FoxPro do not contain the percentage sign character, this
query returns no results.
CLOSE ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'data\testdata')
SELECT * FROM customer;
WHERE company LIKE "%-%--%" Escape "-"
19
Exemplul 7
/Functii agregat cu si fara grupare/
La citi clienti sau trimis facturi?
Solutia 7.1 bazata pe functia COUNT si o subinterogare/subconsultare
SELECT COUNT(*);
FROM clienti;
where codcl IN ;
(SELECT codcl;
FROM facturi)
Solutia 7.2 bazata pe functia COUNT si clauza DISTINCT
SELECT COUNT(DISTINCT codcl);
FROM facturi
Exemplul 8
Care este valoarea totala a facturii 1119, valoarea medie, maxima si minima a produselor vindute pe
aceasta factura?
SELECT SUM(cantitate*pretunit*(1+procTVA) AS Val_Totala;
AVG(cantitate*pretunit+ cantitate*pretunit*procTVA) AS Val_Medie;
MIN(cantitate*pretunit+ cantitate*pretunit*procTVA) AS Val_Minima;
MAX(cantitate*pretunit+ cantitate*pretunit*procTVA) AS Val_Maxima;
FROM produse P INNER JOIN linii Fac. LF;
ON P.codpr=LF.codpr
22
Exemplul 9
Care este valoarea totald a vinzdrilor pentru fiecare zi in care s-au emis facturi :
Pentru rezolvarea problemei este obligatorie folosirea gruparii
SELECT DataFact, SUM(Cantitate * PretUnit * (l+ProcTVA)) AS ValTotala ;
FROM LINIIFACT LF, PRODUSE P, FACTURI F ;
WHERE LF.CodPr = P.CodPr AND LF.NrFact = F.NrFact ;
GROUP BY DataFact
Exemplul 10
Care sunt vtinzarile, cantitativ si valoric, pentru fiecare produs ?
SELECT DenPr, UM, SUM(Cantitate) AS Cantitativ, ;
SUM(Cantitate * PretUnit * (l+ProcTVA)) AS Valoric ;
FROM LINIIFACT LF, PRODUSE P, FACTURI F ;
.WHERE P.CodPr = LF.CodPr AND LF.NrFact = F.NrFact ;
GROUP BY DenPr, UM
Exemplul ll
Sa se oblina situalia vanzarilor pe clienli si zile, afisindu-se cate un subtotal la nivel , client si un total
general.
Varianta propusa, reuneste multimea facturilor propriu-zise, obtinuta din prima fraza SELECT, cu
multimea subtotalurilor la nivel de client (al doilea SELECT) si cu o linie ce reprezintA totalul general.
SELECT PADR(ALLT(dencl),40) As DenumireClient, ;
datafact,;
SUM(Cantitate * PretUnit * (l+ProcTVA)) AS Vinzari ;
FROM liniifact LF, produse P, facturi F, clienti C;
WHERE p.codpr=LF.codpr AND LF.Nrfact=F.Nrfact;
AND F.codcl=C.codcl;
GROUP BY dencl, datafact;
UNION;
SELECT PADR(ALLT(dencl) +-Subtotal,40), { / / },;
SUM(Cantitate * PretUnit * (l+ProcTVA));
FROM liniifact LF, produse P, facturi F, clienti C;
WHERE p.codpr=LF.codpr AND LF.Nrfact=F.Nrfact;
AND F.codcl=C.codcl;
GROUP BY dencl, datafact;
UNION;
SELECT CHR(255)+Total General, { / / },;
SUM(Cantitate * PretUnit * (l+ProcTVA));
FROM liniifact LF, produse P;
WHERE p.codpr=LF.codpr
Exemplul 12
Care sunt zilele in care sau intocmit cel putin 3 facturi?
SELECT datafact, COUNT(*) AS Nr_Facturi;
FROM facturi;
GROUP BY datafact;
HAVING COUNT(*)>=3
23
Exemplul 13
In ce zile s-au vandut si produsul cu denumirea "Produs 1 " si cel cu denumir "Produs 2" ?
Desi are un enunt banal, rezolvarea acestei probleme ofera oportunitatea unor interogari dintre cele mai
spumoase. Va prezentam numai cinci dintre acestea.
.Solutia 13.1.- jonctionarea unei instante obtinuta prin jonctiunea PRODUSE-LINIIFACT-FACTURI (In
care DenPr = 'Produs 1 ') cu o alta instanta aceleiasi combinatii (In care DenPr = 'Produs 2'):
SELECT DISTINCT Fl.DataEact ;
FROM PRODUSE Pl ;
INNER JOIN LINIIFACT LF1;
ON Pl.CodPr = LF1.CodPr ;
INNER JOIN FACTURI Fl ;
ON LF1.NrFact = Fl.NrFact ;
INNER JOIN FACTURI F2;
ON Fl.Datafact=F2,DataFact ;
INNER JOIN LINIIFACT LF2;
ON LF2..Nrfact= F2.NrFact ;
INNER JOIN PRODUSE P2;
ONLF2.CodPr = P2.CodPr ;
WHERE Pl.Denpr = 'Produs l' AND P2.DenPr = 'Produs 2'
.Solutia 13.2- folosind clauza HAVING si functia COUNT:
SELECT DISTINCT DataFact ;
FROM PRODUSE INNER JOIN LINIIFACT ;
ON PRODUSE. CodPr = LINIIFACT. CodPr ;
INNER JOIN FACTURI ;
ON LINIIFACT.Nrfact =FACTURI.Nrfact;
WHERE DenPr;
IN ('Produs l',Produs 2') I;
GROUP BY DataFact ;
HAVING COUNT(DISTINCT LINIIFACT.CodPr) = 2
Solutia 13.3- simuland intersectia prin subconsultari:
SELECT DISTINCT DataFact ;
FROM PRODUSE INNER JOIN LI.NIIFACT ;
ON PRODUSE.CodPr = LINIIFACT.CodPr ;
INNER JOIN FACTURI
ON LINIIFACT.Nrfact = FACTUR.NrFact
WHERE DenPr = 'Produs l' AND DataFact IN ;
(SELECT DISTINCT DataFact ;
FROM PRODUSE ;
INNER JOIN LINIIFACT;
ON PRODUSE.CodPR = LINIIFACT.CodPr ;
INNER JOIN FACTURI;
ON LINIIFACT.Nrfact = FACTURI.NrFact ;
WHERE DenPr = 'Produs 2')
Solutia 13.4 -prin corelarea a doua instante ale jonctiunii PRODUSE-LINIIFACT - FACTURI; prima
contine liniile legate de Produs I, iar a doua de Produs 2:
24
Exemplul 18
Care sunt produsele vandute la preturi unitare superioare oricarui pret unitar la carea fost vandut
'Produs I' ?
Unul dintre obiectivele acestui exemplu este de a prezenta modul de conexiune a unei consultari cu
subconsultarea sa prin operatorul ALL.
SELECT DISTINCT DenPr, PretUnit ;
FROM PRODUSE P, LINIIFACT LF ;
WHERE p.CodPr=LF.CoQP AND Pretunit > ALL ;
(SELECT DISTINCT PretUnit;
FROM PRODUSE P, LINIIFACT LF;
WHERE p.CodPr=LF.CodPr AND DenPr ='Produs 1'
Exemplul 19
Care sunt produsele vandute la preluri unitare superioare macar unui prel unitar al 'Produsului l' ?
Este genul de situatii in care se foloseste SOME sau ANY (au aceeasi functiune).
SELECT DISTINCT DenPr, PretUnit ;
FROM RODUSE P INNER JO1N LINIIFACT LF ,
ON P.CodPr=LF.CodPr ;
WHERE PretUnit > ANY;
(SELECT DISTINCT PretUnit ;
FROM PRODUSE P INNER JOIN LINIIFACT
ON P.CodPr=LF.CodPr ;
WHERE DenPr ='Produs 1')
Exemplul 20
Care este ultima factura intocmita /factura cea mai recenta/ si data in care a fost remisa ?
Aceasta este o problema cu multe variante de rezolvare
Solutie 20.1
SELECT DataFact, NrFact AS Ultima_Factura ;
FROM facturi;
WHERE NrFact IN;
(SELECT MAX(Nrfact);
FROM facturi)
Solutie 20.2 in locul operatorului de conexiune IN este utilizat semnul =
SELECT DataFact, NrFact AS Ultima_Factura ;
FROM facturi;
WHERE NrFact =;
(SELECT MAX(Nrfact);
FROM facturi)
Solutie 20.3 in locul operatorului de conexiune IN este utilizat operatorul ANY
SELECT DataFact, NrFact AS Ultima_Factura ;
FROM facturi;
WHERE NrFact = ANY;
(SELECT MAX(Nrfact);
FROM facturi)
27
28
O data creat si declarate restrictiile, un cursor poate fi actualizat ca orice tabela obisnuita, prin comenzile
SQL: INSERT, UPDATE si DELETE, precum si orice alta comanda de editare specifica VFP. De
asemenea, orice incalcare a vreunei restrictii definite va fi sernnalizata. Cursoarelor, similar tabelelor
virtuale, li se pot vizualiza si configura proprietatile prin functiile CURSORGETPROP( ) si
CURSORSETPRQP().
Continutul unui cursor poate fi adaugat la inregistrarile curente ale unei tabele prin comanda
30
- numele clientului,
- localjtatea in care-si are sediul c1ientul,
- valoarea incasata pana in momentul curent trebuie obtinuta pentru un anumit interval calendaristic, in orice ordine declarata prin toate combinatiile
posibile ale celor cinci cimpuri
Iata o varianta de program
PROCEDURE listare1
PARAMETER datainf_,datasup_,cimp1_,cimp2_,cimp3_,cimp4_
SELECT Dencl AS Client, Loc As Localitate, Nrfact, DataFact, Gestiune, ValTotala AS Valoare;
FROM clienti C LEFT OUTER JOIN facturi F
ON C.codcl=F.codcl;
INNER JOIN LOCALITATI L
ON C.CodPost = L.CodPost;
WHERE Datafact BETWEEN datainf_ AND datasup_ ;
ORDER BY &cimp1, &cimp2_, &cimp3_, &cimp4_
RETURN
ENDPROC
Clauza ORDER BY se construieste dinamic cu ajutorul macrosubstitutiei.
Lansarea acestui program se face cu comanda DO:
DO listare1 WITH {^2001/08/02}, {^2001/08/07}, 'Loc', 'DataFact', 'DenCl', 'ValTotala'
In continuare se propune o varianta mai eleganta.
Ce-ar fi ca, in arara celor doua date calendaristice, de inceput si de sfarsit, ordonarea sa fie precizata
printr-o lista care sa contina unul, doua, trei. ..sau chiar nici un atribut?
Programul ce urmeaza preia un parametru de tip sir de caractere care este, de rapt, lista atributelor de
ordonare, atribute separate prin virgula.
Asa incat programul analizeaza virgulele din sir si extrage atributele pe baza carora se va construi,
dinamic, clauza WHERE.
In exemplul ce urmeaza se preia numai data initiala si finala, plus ordinea de prezentare, sub forma
de lista de atribute separate prin virgula
Returns the beginning numeric position of the first occurrence of a character expression or memo field
within another character expression or memo field, counting from the leftmost character. La inceput sa
facem cunostinta cu functia AT()
Syntaxa
AT(cSearchExpression, cExpressionSearched [, nOccurrence])
Returns
Numeric
Arguments
cSearchExpression
Specifies the character expression that AT( ) searches for in cExpressionSearched.
cExpressionSearched
Specifies the character expression cSearchExpression searches for.
Both cSearchExpression and cExpressionSearched can be memo fields of any size.
nOccurrence
Specifies which occurrence (first, second, third, and so on) of cSearchExpression is searched for in
cExpressionSearched. By default, AT( ) searches for the first occurrence of cSearchExpression
33
(nOccurrence = 1). Including nOccurrence lets you search for additional occurrences of
cSearchExpression in cExpressionSearched. AT( ) returns 0 if nOccurrence is greater than the number
of times cSearchExpression occurs in cExpressionSearched.
Remarks
AT( ) searches the second character expression for the first occurrence of the first character expression.
It then returns an integer indicating the position of the first character in the character expression found.
If the character expression isn't found, AT( ) returns 0.
The search performed by AT( ) is case-sensitive. To perform a search that isn't case-sensitive, use
ATC( ).
PROCEDURE listare2
PARAMETER datainf_, datasup_, ordinea_
I=1
*se determina prima pozitie a virgulei (asta inseamna cu sunt macar
*doua atribute de ordonare)
poz_ = AT (',', ordinea_, i)
IF poz_ > 0
&& exista macar o virgula, deci sunt mai multe atribute de ordonare
Order_by_=ALLTRIM(ordinea_)
ENDIF
ENDIF
* si acum presentam propriu zis ordonarea
SELECT Dencl AS Client, Loc As Localitate, Nrfact, DataFact, Gestiune, ValTotala AS Valoare;
FROM clienti C LEFT OUTER JOIN facturi F
ON C.codcl=F.codcl;
INNER JOIN LOCALITATI L
ON C.CodPost = L.CodPost;
WHERE Datafact BETWEEN datainf_ AND datasup_ ;
ORDER BY &order_by_
RETURN
ENDPROC
Prezentam 3 moduri de adresare la programul prezentat mai sus
DO listare2 WITH {^2001/08/02}, {^2001/08/07}, 'ValTotala,Dencl,NrFact'
DO listare2 WITH {^2001/08/02}, {^2001/08/07}, 'NrFact'
DO listare2 WITH {^2001/08/02}, {^2001/08/07}, ' '
Zi 02 08 2001
Zi 03 08 2001
Zi 04 08 2001
Pentru facilitarea prezentarii, sa ne limitam la patru zile, dar programul ce urmeaza functioneaza pentru
oricate zile dorim, singura problema fiind completarea cursorului ZILE.
In prograrnul ce urmeaza, aceasta se face prin INSERT-uri directe, insa in aplicatii datele initiale si
finale ale intervalului se pot prelua printr-un formular si, astfel, completarea cursorului se
automatizeaza.
SET MARK TO '_'
FROM Zile) ;
GROUP BY DataFact, DenPr, LF.CodPr
SELECT DenPr, CodPr;
INTO CURSOR c1 ;
FROM PRODUSE ;
ORDER BY DenPr
i= 1
SELECT Zile
SCAN
ii = ALL T(STR(i,2))
ii_plus_1 = ALL T(STR(i+1 ,2))
ziua_= '_'+DTOC(Zile.Zi)
SELECT c&ii..*, NVL(ZILE_PRODUSE.Valoare,0) AS Zi&ziua_ ;
FROM c&ii LEFT OUTER JOIN ZILE_PRODUSE ;
ON c&ii..CodPr = ZILE_PRODUSE.CodPr AND DataFact = Zile.Zi ;
INTO CURSOR c&ii_plus_1
i=i+ 1
SELECT Zile
ENDSCAN
SELECT c&ii_plus_1
BROWSE TITLE 'Vinzari_Produse/Zile'
SELECT Zile
USE
SELECT Zile_Produse
USE
FOR j=1 TO i
ii = ALLT(STR(j,2))
SELECT c&ii
USE
ENDFOR
Cateva explicatii. Cursorul ZILE contine toate datele calendaristice care trebuie sa apara drept coloane
ale raportului.
Valorile vanzarilor pe produse si zile sunt calculate si stocate in cursorul Z ILE_PRODUSE.
Liniile raportului sunt alcatuite din toate produsele firmei, astfel incat cursorul "de start" - C1 -este
obtinut din tabela PRODUSE.
Numarul iteratiilor depinde de numarul inregistrarilor din cursorul ZILE - numarul zilelor pentru care
intereseaza raportul.
Corpul ciclului contine jonctiunea cursorului "curent" cu ziua corespunzatoare inregistrarii curente din
cursorul ZILE.
36