Lab - VFP - SQL
Lab - VFP - SQL
10
NUCLEUL SQL DIN VISUAL FOXPRO 6.0.
Exemple de interogări
Selecţia, proiecţia , reuniunea
Pornind de la tabelele Agenti1 şi Agenti2 , tabelul reuniune care reprezintă tabelul AGENTI va fi
obţinut în SQL prin fraza:
SELECT *;
FROM AGENTI1;
UNION;
SELECT *;
FROM AGENTI2;
Funcţia COUNT
Câţi clienţi are firma?
SELECT COUNT (cod) AS nr_clienti;
FROM Agenti
Câte formulare de facturi au fost anulate?
SELECT COUNT (anulat);
FROM NRSP;
WHERE anulat="Da"
Câte facturi s-au emis în data de 29.01.1999
SELECT COUNT (DISTINCT numar);
FROM FACTURI;
WHERE Data={^1999-01-29}
Funcţia SUM
Calculează suma valorilor unei coloane.
Care este valoarea totală a facturilor emise?
SELECT SUM(Val) AS Total_fe;
FROM Facturi
Care este valoarea apei potabile facturate?
SELECT SUM(Val) AS Total_fe;
FROM Facturi;
WHERE tip=12
Care este valoarea facturii emise pentru AKROM AKAL?
SELECT SUM(val) AS Total_ELCO;
FROM FACTURI, AGENTI;
WHERE FACTURI.cod=AGENTI.cod AND AGENŢI.nume="AKROM AKAL"
sau
SELECT SUM(val) AS Total_ELCO;
FROM FACTURI;
WHERE cod IN;
(SELECT cod;
FROM AGENTI;
WHERE nume="AKROM AKAL" )
Funcţia AVG
Calculează media aritmetică a unei coloane într-un tabel oarecare, prin divizarea sumei
valorilor coloanei respective la numărul de valori nenule ale acesteia.
Care este valoarea medie a prestaţiilor facturate în factura cu numărul 10589?
SELECT AVG (Pret*Cant) AS Medie_10589;
FROM FACTURI;
WHERE Numar=10589
Observaţie: Valoarea medie a tuturor facturilor nu poate fi calculată cu funcţia AVG. In acest caz
este necesară utilizarea opţiunii GROUP BY.
Care este valoarea medie a serviciilor de canalizare facturate?
SELECT AVG (Pret*Cant) AS Medie_canal;
FROM FACTURI;
WHERE tip=22
Care este valoarea medie facturată pentru serviciile de canal în zonele Burdujeni şi Iţcani?
SELECT AVG (Pret*Cant) AS Medie_canal;
FROM FACTURI;
WHERE tip=22 AND cod IN;
(SELECT cod;
FROM AGENTI;
WHERE Zona IN ("BURDUJENI","Iţcani")
Funcţiile MAX şi MIN
Determină valorile maxime, respectiv minime ale unei coloane în cadrul unui tabel.
Care este codul agentului pentru care s-a facturat cea mai mare cantitate de apă?
SELECT cod ;
FROM Facturi;
WHERE val IN;
(SELECT MAX (Val);
FROM Facturi;
WHER tip=12)
Gruparea tuplurilor. Clauzele GROUP BY şi HAVING
SQL permite utilizarea clauzei GROUP BY pentru a forma grupuri de tupluri într-o relaţie
pe baza valorilor comune ale unei coloane. Prin asocierea unei clauze HAVING la o clauză
GROUP BY este posibilă selectarea anumitor grupe de tupluri care îndeplinesc un criteriu.
Formatul general al clauzei GROUP BY este:
SELECT col1, col2,..coln;
FROM tabel;
GROUP BY coloană de grupare
Care este totalul valorilor facturate pentru fiecare serviciu prestat?
SELECT Tip, Produs, SUM(val);
FROM FACTURI ;
GROUP BY Tip
In acest caz tabelul rezultat va aveaun număr de linii egal cu numărul tipurilor de prestaţii distincte
dintabelul Facturi. Pentru toate poziţiile din facturi care se referă la un anumit produs se va calcula
suma valorilor deoarece se foloseşte funcţia SUM.
Care este numărul facturilor trimise în fiecare zonă a orasului?
SELECT Zona, COUNT(numar);
FROM AGENTI, NRSP;
WHERE AGENTI.cod=NRSP.cod;
GROUP BY AGENTI.Zona
Care este valoarea totală a facturilor emise, pe zile, pentru fiecare zona ?
SELECT Zona, Data, SUM (val);
FROM Facturi, Agenti;
WHERE Facturi.cod=Agenţi.cod ;
GROUP BY Zona, Data
Clauza HAVING
Clauza HAVING lucrează împreună cu o clauză GROUP BY, fiind practic o clauză WHERE
aplicată acesteia. Formatul general este:
SELECT col1, col2,..coln;
FROM tabel;
GROUP BY coloană de regrupare;
HAVING caracteristică de grup
Pentru facturile emise, interesează valoarea zilnică, dar numai dacă această valoare este mai
mare de 5.000.000 lei.
SELECT Data, SUM(val);
FROM Facturi;
GROUP BY Data;
HAVING SUM(val)>5000000
Care sunt agenţii pentru care în facturi există mai mult de două poziţii pentru un produs
furnizat?
SELECT nume;
FROM Agenti;
WHERE cod IN;
(SELECT cod;
FROM FACTURI;
GROUP BY tip, cod;
HAVING COUNT(*)>2)
SQL IN VFP
DIN VFP HELP
Structured Query Language (SQL) commands.
Visual FoxPro supports the following SQL commands:
SELECT - SQL
You can create a SELECT command query in these areas:
• In the Command window.
• In a Visual FoxPro program (like any other Visual FoxPro command).
• In the Query Designer.
ALTER TABLE - SQL
Modifies an existing table. You can modify the name, type, precision, scale, null value support, and
referential integrity rules for each field in the table.
CREATE CURSOR - SQL
Creates a temporary table. Each field in the temporary table is defined with a name, type, precision,
scale, null value support, and referential integrity rules. These definitions can be obtained from the
command itself or from an array.
CREATE TABLE -SQL
Creates a table. Each new table field is defined with a name, type, precision, scale, null value
support, and referential integrity rules. These definitions can be obtained from the command itself or
from an array.
DELETE - SQL
Marks records in a table for deletion using SQL syntax.
INSERT - SQL
Appends a new record to the end of an existing table. The new record contains data listed in the
INSERT command or from an array.
UPDATE - SQL
Updates records in a table. The records can be updated based on the results of a SELECT - SQL
statement.
INTRODUCERE
******program care prezinta crearea si manipularea cu datele a unei BD prin intermediul SQL -
******comenzilor
********** Tabelul 2
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]
-or-
ALTER TABLE TableName1
ALTER [COLUMN] FieldName2
[NULL | NOT NULL]
[SET DEFAULT eExpression2]
[SET CHECK lExpression2 [ERROR cMessageText2]]
[DROP DEFAULT]
[DROP CHECK]
[NOVALIDATE]
-or-
ALTER 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
* 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 orders ALTER COLUMN quantity DROP CHECK
* Example 6
ALTER TABLE orders DROP FOREIGN KEY TAG cust_id SAVE
* Example 7
CLEAR
ALTER TABLE customer ADD COLUMN fax2 c(20) NOT NULL
DISPLAY STRUCTURE
Redenumirea unui atribut, il poate face doar VFP printere cele mai renumite SGBD-uir
Stergerea unui atribut, sa zicem pe cel pe care numai ce l-am adaugat se va face prin
comanda
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, ...])
-or-
INSERT 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
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. The contents of the
current record are scattered to variables, and the table's structure is copied to a new table named
cust2. INSERT - SQL is used to insert a new record in the cust2 table, and BROWSE is issued to
display the new record.
CLOSE DATABASES
CLEAR
SELECT CUST2
BROWSE
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
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'Data\testdata')
USE customer && Opens Customer table
SELECT PRODUSE
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
Remarca
Modificarea se produce pe toate liniile tabelei care indeplinesc conditia formulata prin
predicat.
De exemplu
Noul numar de telefon al clientului ce are codul 1001 este 032-313131. Sa se opereze
modificarea in baza de date
UPDATE CLIENT;
SET telefon =’032-313131’;
WHERE codcl=1001
UPDATE PRODUSE;
SET procTVA=0.22;
Example 8
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 "-"
Exemple cu referinta la Structura BD create in primul punct
Exemplul 1
Presupundnd ca plata se face la 14 zile, care sunt facturile ce urmeaza a fi incasate in perioada
15-18 august 2001 ?
Solutia 1.1
Exemplul 2
Care sunt clienlii din din Anenii Noi si Criuleni?
Solutia 2.1 :
SELECT CLIENTI.* ;
FROM CLIENTI INNER JOIN LOCALITATI ;
ON CLIENTI.CodPost = LOCALITATI.CodPost ;
WHERE Loc=’Anenii Noi’ OR Loc=’Criuleni’
SELECT CLIENTI.* ;
FROM CLIENTI INNER JOIN LOCALITATI ;
ON CLIENTI.CodPost = LOCALITATI.CodPost ;
WHERE Loc IN ('Anenii Noi', 'Criuleni')
SELECT CLIENTI.* ;
FROM CLIENTI, LOCALITATI ;
WHERE CLIENTI.CodPost = LOCALITATI.CodPost AND Loc ;
IN ('Anenii Noi', 'Criuleni')
SELECT C.* ;
FROM CLIENTI C, LOCALITATI L ;
WHERE C.CodPost = L.CodPost AND ;
Loc IN ('Anenii Noi', 'Criuleni')
Exemplul 3
Ce persoane cheie trebuie felicitate de Sfintul ION?
Exemplul 4
Ce persoane chepe de la firmele client un au e-mail?
Exemplul 6
Care dintre persoanele din tabela cu acelasi nume un au functii la firmele client?
ON p.cnp=pc.cnp;
WHERE NVL(PC.codcl,0)=0
Exemplul 7
/Functii agregat cu si fara grupare/
La citi clienti sau trimis facturi?
Exemplul 8
Care este valoarea totala a facturii 1119, valoarea medie, maxima si minima a produselor vindute
pe aceasta factura?
Exemplul 9
Care este valoarea totald a vinzdrilor pentru fiecare zi in care s-au emis facturi :
Pentru rezolvarea problemei este obligatorie folosirea gruparii
Exemplul 10
Care sunt vtinzarile, cantitativ si valoric, pentru fiecare produs ?
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.
Exemplul 12
Care sunt zilele in care sau intocmit cel putin 3 facturi?
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.4 -prin corelarea a doua instante ale jonctiunii PRODUSE-LINIIFACT - FACTURI;
prima contine liniile legate de Produs I, iar a doua de Produs 2:
Solutia 13.5:
Exemplul 14
Afisarea pe coloane separate, pentru cele trei gestiuni, a facturilor necesita folosirea unei
secvente de IF-uri immediate (IIF-uri):
SELECT IIF(gestiune = '001', STR(F.NrFact,8), space{8)) ;
AS Gestiune 001, ;
IIF(gestiune ='002’, STR{F.NrFact,8), space{8)) ;
AS Gestiune 002, ;
IIF(gestiune ='003’, STR{F.NrFact,8), space{8)) ;
AS Gestiune 003, ;
DataFact, SUM(Cantitate * PretUnit * (l+ProcTVA)) ;
AS ValTotala ;
FROM FACTURI F ;
INNER JOIN LINIIFACT LF
ON F.NrFact = LF.NrFact ;
INNER JOIN PRODUSE P
ON LF.CodPr = P.CodPr ;
GROUP BY F.NrFact
Exemplul 15
Scadenla fiecarei facturi emise este de 20 de zile. Daca insa data-limita cade intr-o sambata sau
duminica, atunci scadenla se muta in lunea urmatoare. Care sunt zilele, scadente in aceste
condilii ?
Visual FoxPro prezinta functiile CDOW (Character Day Of the Week) si DOW (Day of the Week).In
acest caz putem obtine urmatorul rezultat.
SELECT NrFact AS Factura, DataFact, ;
DataFact + 20 AS Scadental, ;
CDOW(DataFact+20) AS NumeZil, ;
IIF(DOW(DataFact+20)=6, ;
DataFact+22, ;
IIF(DOW(DataFact+20)=1, ;
DataFact+21, ;
DataFact+20) ) AS Scadenta,;
CDOW(IIF(DOW(Datafact+20)=6,;
DataFact+22, ;
IIF(DOW(DataFact+20)=1, ;
DataFact+21,;
DataFact+20) ) ) AS ZI_Scadenta ;
FROM FACTURI
Exemplul 16
Care sunt valorile facturate si incasate ale fieciirei facturi ?
Solutia de mai jos, reune~te facturile care au macar o transa de incasare cu cele nelncasate deloc:
SELECT F. NrFact, ;
SUM(Cantitate *PfretUnit * (l+ProcTVA).) / ;
COUNT (DISTINCT I..CodInc) AS Facturat, ;
SUM(Transa) / MAX(LF.Linie) AS Incasat ;
FROM LINIIFACT LF, PRODUSE P, FACTURI F, INCASFACT I ;
WHERE LF.CodPr = P.CodPr AND LF.NrFact = F.NrFact ;
AND F.NrFact=I.NrFact ;
GROUP BY F.NrFact ;
UNION ;
SELECT F. NrFact, ;
SUM(Cantitate * P+PretUpit * (l+ProcTVA)) AS Facturat,
0 AS Incasat ;
FROM LINIIFACT LF, PRODUSE P, FACTURI F ;
WHERE LF.CodPr = P.CodPr AND LF.NrFact = F.NrFact ;
AND F.NrFact NOT IN ;
(SELECT NrFact ;
F'ROM INCASFACT) ;
GROUP BY F.NrFact
Exemplul 17
Care sunt cele mai mari cinci preluri unitare de vanzare, produsele si facturile in care apar cele
cinci preluri maxime?
In alte SGBD-uri, aceasta problema ar crea mari dureri de cap. Clauza TOP din VFP realizeaza
ordonarea si extragerea celor cinci valori relative simplu )
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.
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).
Solutie 20.1
SELECT DataFact, NrFact AS Ultima_Factura ;
FROM facturi;
WHERE NrFact IN;
(SELECT MAX(Nrfact);
FROM facturi)
Exemplul 21
Care este gestiunea cu vinzarile cele mai bune ?
Daca in alte SGBD-uri sunt necesare subconsultari in clauza FROM, in VFP, aceasi clauza TOP
salveaza totul!
Multe din necesitatile VFP necesita folosirea in SQL a mai multor nivele de subconsultare in mod
deosebit in propozitiile FROM sau HAVING. Aceste facilitate nucleul SQL in VFP nu le are in
deplina masura si putere.
In schim in VFP aceste rezultate se pot crea ca rezultate intermediare stocate in CURSOARE sau
TABELE virtuale care la rindul lor pot fi utilizate ca argumente in alte noi consultari.
CURSORUL este in VFP o tabelea temporara care exista din momentul formarii comenzii SELECT
cu clauza INTO CURSOR sau CREATE CURSOR si pina la includerea sa implicita sau explicita
La seria interogarilor care au fost prezentate deja mai adaugam si o varianta simpla de program dupa
cum urmeaza
SELECT *;
FROM Zile_P1
WHERE DataFact IN
(SELECT DataFact;
FROM ZILE_P2)
Prima interogare creaza cursoul Zile_P1 si contine numai zilele in care s-a vindut primul produs.
Zile_P2 este cursorul ce tine de zilele cind s-a vindut al doilea produs.
Ultima interogare contine intersectia celor doua cursoare ce rezolva problema
Exemplul 22
Care este raionul cu vinzari imediat superioare raionului Anenii Noi ?
Interesul este aici ca in WHERE are loc jonctiunea care solutioneaza cazul
Un cursor poate ti creat si prin comanda CREATE CURSOR, caz in care tabela temporara este
actualizabila. Formatul comenzii prezinta clauze similare CRE
Syntaxa
CREATE CURSOR alias_name
(fname1 type [(precision [, scale])
[NULL | NOT NULL]
[CHECK lExpression [ERROR cMessageText]]
[DEFAULT eExpression]
[UNIQUE]
[NOCPTRANS]]
[, fname2 ...])
| FROM ARRAY ArrayName
Din HELP VFP
The following example creates a cursor with the alias employee. A blank record is appended, filled, and displayed
with the BROWSE command.
CLOSE DATABASES
CLEAR
CREATE CURSOR employee ;
(EmpID N(5), Name C(20), Address C(30), City C(30), ;
PostalCode C(10), OfficeNo C(8) NULL, Specialty M)
DISPLAY STRUCTURE
WAIT WINDOW "Press a key to add a record."
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
APPEND FROM DBF ( '<NumeCursor>' ) .
Program de calcul al reducerilor acordate pentru incasari si anume pentru transele de facturi
platite /INCASARI.DataInc/
in termen de pina la 10 zile se acorda o reducere de 10%
intre 11 si 12 zile se acorda o reducere de 9%
intre 13 si 15 zile se acorda o reducere de 8%
peste 16 zile nu se acorda nici o favaore /in realitate se acorda penalizari/
Transele acordate a reducerilor pot fi stocate in cursoare si astfel folosite la interogari.
Este o solutie nu prea simpla dar operationala!!! Aici pielea costa cit dubala!
Exemplu.
De listat facturile emise catre un client pentru un anumit interval de timp definit de o data initiala si
una finala.
Programul ce urmeaza este o procedura si la ea se poate de adresat cu parametri
PROCEDURE listare
PARAMETER codcl_, datainf_,datasup_
SELECT DenCI AS Client, Nrfact, DataFact, Gestiune, ValTotala AS Valoare;
FROM clienti C LEFT OUTER JOIN facturi F
ON C.codcl=F.codcl;
WHERE F.codcl=codcl_ AND datafact BETWEEN datainf_ AND datasup_
RETURN
ENDPROC
Pentru a obtine lista clientului 1 /cod 1001/ in perioada 2-7 august 2001 apelam la procedura scrisa
dupa cum urmeaza
PROCEDURE listare
PARAMETER codcl_, datainf_,datasup_
SELECT DenCI AS Client, Nrfact, DataFact, Gestiune, ValTotala AS Valoare;
INTO CURSOR c1 ;
FROM clienti C LEFT OUTER JOIN facturi F
ON C.codcl=F.codcl;
WHERE F.codcl=codcl_ AND datafact BETWEEN datainf_ AND datasup_
Titlu_=’Lista facturilor pentru clientul’+ALLTRIM(c1.client)+’in perioada’+ ;
DTOC(datainf_)+’-‘+DTOC(datasup_)
SELECT C1
BROWSE TITLE Titlu_
RETURN
ENDPROC
Important este ca in asa mod obtinem rezultatele fara a incarca memoria cu “Gunoi” adica tabele in
plus
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:
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
(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
IF poz_ > 0 && exista macar o virgula, deci sunt mai multe atribute de ordonare
* se localizeaza toate virgulele si se extrag atributele cuprinse intre virgule
poz_preced = O
DO WHILE poz_ # O
ii = str(i,1)
cimp&ii = SUBSTR(ordinea_, poz_preced + 1, poz_ -poz_preced -1 )
poz_preced = poz_
i = i+ 1
poz_ = AT (',', ordinea_, i)
ENDDO
ii = str(i,1)
cimp&ii = SUBSTR(ordinea_, poz_preced + 1, LEN(ordinea_) -poz_preced)
order_by_ = ‘ ’
FOR j = 1 TO i
jj = STR(j,1)
IF j > 1
order_by_ = order_by_ + ‘,’
ENDIF
order_by_ = order_by_ + ALLTRIM(cimp&jj)
ENDFOR
ENDIF
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 '_' && separatorul pentru data calendaristica
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.