Pr Vysoká škola báňská Technická univerzita Ostrava Fakulta strojní, Katedra automatizační techniky a řízení 2008/2009 Radim Farana 1 Řešený příklad Vytvořte aplikaci pro sledování pracovních výkonů jednotlivých pracovníků a výpočet jejich denní odměny na základě stanovených cen za výkon jednotlivých typů práce. 2 Struktura navržené databáze 3 1
Vytvoření databáze CREATE TABLE [dbo].[platy] ALTER TABLE ( [dbo].[platy] WITH NOCHECK ALTER ADD TABLE [dbo].[platy] ADD [pl_id] [int] IDENTITY CONSTRAINT (1, 1) NOT NULL [PK_Platy], PRIMARY KEY CONSTRAINT CLUSTERED [FK_Platy_Pracovnici] FOREIGN KEY [pl_pracovnik] [int] NULL (, ( [pl_datum] [datetime] NULL, [pl_id] [pl_pracovnik] [pl_castka] [money] NULL ) ON [PRIMARY] ) REFERENCES [dbo].[pracovnici] ( ) ON [PRIMARY] [pr_osc] ALTER TABLE [dbo].[pracovnici] WITH NOCHECK ADD ) CREATE TABLE [dbo].[pracovnici] ( CONSTRAINT [PK_Pracovnici] PRIMARY KEY CLUSTERED [pr_osc] [int] NOT NULL (, ALTER TABLE [dbo].[prace] ADD [pr_jmeno] [varchar] (50) COLLATE [pr_osc] Czech_CI_AS NULL CONSTRAINT [FK_prace_Pracovnici] FOREIGN KEY ) ON [PRIMARY] ) ON [PRIMARY] ( [p_pracovnik] CREATE TABLE [dbo].[prace] ALTER TABLE ( [dbo].[prace] WITH NOCHECK ADD ) REFERENCES [dbo].[pracovnici] ( [p_id] [int] IDENTITY CONSTRAINT (1, 1) NOT NULL [PK_prace], PRIMARY KEY CLUSTERED [pr_osc] [p_pracovnik] [int] NOT ( NULL, ), [p_typ] [varchar] (50) COLLATE Czech_CI_AS [p_id] NULL, CONSTRAINT [FK_prace_typyprace] FOREIGN KEY [p_kusu] [float] NULL ), ON [PRIMARY] ( [p_datum] [datetime] NULL [p_typ] ) ON [PRIMARY] ALTER TABLE [dbo].[typyprace] WITH NOCHECK ADD ) REFERENCES [dbo].[typyprace] ( CONSTRAINT [PK_typyprace] PRIMARY KEY CLUSTERED [tp_nazev] CREATE TABLE [dbo].[typyprace] (( ) ON UPDATE CASCADE [tp_nazev] [varchar] (50) COLLATE [tp_nazev] Czech_CI_AS NOT NULL, [tp_popis] [text] COLLATE ) ON Czech_CI_AS [PRIMARY] NULL, [tp_cena] [money] NULL ) ON [PRIMARY] TEXTIMAGE_ON ALTER TABLE [PRIMARY] [dbo].[platy] ADD CONSTRAINT [CK_Platy] CHECK ([pl_castka] > 10000) 4 Testovací data INSERT INTO typyprace (tp_nazev, tp_popis, tp_cena) VALUES ('kvákání','skupinové',1000); INSERT INTO typyprace (tp_nazev, tp_popis, tp_cena) VALUES ('praní','každý kousek zvlášť',10); INSERT INTO typyprace (tp_nazev, tp_popis, tp_cena) VALUES ('spaní','celou noc',120); INSERT INTO typyprace (tp_nazev, tp_popis, tp_cena) VALUES ('škudlení','každý okamžik',1); INSERT INTO typyprace (tp_nazev, tp_popis, tp_cena) VALUES ('hrdlení','jen mezi příbuznými',25); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (122,'Jan Kvákal'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (123,'Patrik Svatý'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (124,'Ivanka Desátá-Jedenáctá'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (125,'Jean-Dean Sikorski'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (126,'Patricia de Souza y Cachal de Brito'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (127,'Jan Pavel I'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (128,'Karla Osmá'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (130,'Orgoj Chorchoj'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (131,'Piotr Ivanovič Ustinovskij'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (133,'Jana Růžena Kostičkovitá'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (140,'Jan Evangelista Svatovítský'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (141,'Ian z Glenyanu'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (152,'Pavla Ospalá'); INSERT INTO Pracovnici (pr_osc, pr_jmeno) VALUES (153,'Karel Ospalý'); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (122,'praní',4, CAST ( '03/12/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (122,'praní',5, CAST ( '03/13/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (123,'škudlení',12, CAST ( '03/14/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (131,'praní',1, CAST ( '03/13/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (131,'praní',5, CAST ( '03/14/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (131,'škudlení',18, CAST ( '03/15/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (140,'praní',20, CAST ( '03/12/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (140,'praní',2, CAST ( '03/13/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (140,'praní',31, CAST ( '03/14/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (128,'praní',3, CAST ( '03/15/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (128,'škudlení',2, CAST ( '03/12/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (128,'praní',6, CAST ( '03/13/2006' AS DateTime)); INSERT INTO prace (p_pracovnik, p_typ, p_kusu, p_datum) VALUES (128,'praní',7, CAST ( '03/14/2006' AS DateTime)); 5 Agregace Určete počet záznamů o práci pro jednotlivé pracovníky SELECT p_pracovnik, COUNT(p_id) as Pocet FROM prace GROUP BY p_pracovnik; p_pracovnik Pocet ----------- ----------- 122 2 123 1 128 4 131 3 140 3 (5 row(s) affected) 6 2
Agregace Určete průměrný počet kusů ze všech záznamů práce SELECT AVG(p_kusu) FROM prace; 8.9230769230769234 (1 row(s) affected) 7 Agregace Určete průměrný počet kusů pro jednotlivé druhy práce SELECT p_typ, AVG(p_kusu) FROM prace GROUP BY p_typ; p_typ --------------- ------------------ praní 8.4000000000000004 škudlení 10.666666666666666 (2 row(s) affected) 8 Vnořený dotaz vracející skalární hodnotu Určete záznamy o práci s nadprůměrným počtem kusů SELECT * FROM prace WHERE p_kusu> (SELECT AVG(p_kusu) FROM prace); p_id p_pracovnik p_typ p_kusu p_datum ----------- ----------- ------------- --------- ---------------------- 6 123 škudlení 12.0 2006-03-14 00:00:00.000 9 131 škudlení 18.0 2006-03-15 00:00:00.000 10 140 praní 20.0 2006-03-12 00:00:00.000 12 140 praní 31.0 2006-03-14 00:00:00.000 (4 row(s) affected) 9 3
Vnořený dotaz s propojením Určete záznamy o práci s nadprůměrným počtem kusů v rámci stejného druhu práce SELECT * FROM prace WHERE p_kusu> (SELECT p_id AVG(p_kusu) p_pracovnik p_typ p_kusu p_datum FROM prace As TMP WHERE TMP.p_typ=prace.p_typ); ----------- ----------- ------------- ------ --------------------------- 10 140 praní 20.0 2006-03-12 00:00:00.000 12 140 praní 31.0 2006-03-14 00:00:00.000 6 123 škudlení 12.0 2006-03-14 00:00:00.000 9 131 škudlení 18.0 2006-03-15 00:00:00.000 (4 row(s) affected) 10 Vnořený dotaz vracející vektor hodnot Určete všechny práce, kterých bylo v jednom dni více než tři (vnořený dotaz) SELECT * FROM prace WHERE p_datum In (SELECT p_datum p_id p_pracovnik p_typ p_kusu p_datum ----------- ----------- ------ ------------ ----------------------- FROM 15 prace128 praní 6.0 2006-03-13 00:00:00.000 11 140 praní 2.0 2006-03-13 00:00:00.000 5 122 praní GROUP 7 BY 131 p_datum praní 5.0 1.0 2006-03-13 00:00:00.000 2006-03-13 00:00:00.000 8 131 praní 5.0 2006-03-14 00:00:00.000 HAVING 6 Count(*)>3) 123 škudlení 12.0 2006-03-14 00:00:00.000 12 140 praní 31.0 2006-03-14 00:00:00.000 ORDER 16 BY 128 p_datum; praní 7.0 2006-03-14 00:00:00.000 (8 row(s) affected) 11 Vnořený dotaz s propojením vracející vektor hodnot Určete všechny práce, kterých bylo v jednom dni více než dvě stejného druhu SELECT * FROM prace WHERE p_datum In (SELECT p_datum p_id p_pracovnik p_typ p_kusu p_datum FROM prace ------ as ----------- TMP --------- ------ ----------------------- 5 122 praní 5.0 2006-03-13 00:00:00.000 GROUP BY 7 p_datum,p_typ 131 praní 1.0 2006-03-13 00:00:00.000 11 140 praní 2.0 2006-03-13 00:00:00.000 HAVING Count(*)>2 15 128 AND praní TMP.p_typ=prace.p_typ) 6.0 2006-03-13 00:00:00.000 16 128 praní 7.0 2006-03-14 00:00:00.000 ORDER BY 12 p_datum; 140 praní 31.0 2006-03-14 00:00:00.000 8 131 praní 5.0 2006-03-14 00:00:00.000 (7 row(s) affected) 12 4
Spojení tabulek Určete pro každou osobu a den výdělek za jednotlivé práce (počet kusů krát cena) p_pracovnik SELECT p_pracovnik, p_datum, Plat 122 2006-03-12 00:00:00.000 40.0 p_kusu*tp_cena As 122 Plat 2006-03-13 00:00:00.000 50.0 123 2006-03-14 00:00:00.000 12.0 131 2006-03-13 00:00:00.000 10.0 FROM prace INNER 131 JOIN 2006-03-14 typyprace 00:00:00.000 On 50.0 p_typ=tp_nazev; 131 2006-03-15 00:00:00.000 18.0 140 2006-03-13 00:00:00.000 20.0 ----------- ------------------------- ------ 140 2006-03-12 00:00:00.000 200.0 140 2006-03-14 00:00:00.000 310.0 128 2006-03-15 00:00:00.000 30.0 128 2006-03-12 00:00:00.000 2.0 128 2006-03-13 00:00:00.000 60.0 128 2006-03-14 00:00:00.000 70.0 (13 row(s) affected) 13 Spojení dat spolu s agregací Určete pro každou osobu a den celkový výdělek Suma(počet kusů krát cena) p_datum SELECT p_pracovnik,p_datum, Sum(p_kusu*tp_cena) 128 As 2006-03-12 Plat 00:00:00.000 2.0 FROM prace INNER JOIN typyprace On p_typ=tp_nazev GROUP BY p_pracovnik,p_datum; Plat ----------- ------------------------- ----- 122 2006-03-12 00:00:00.000 40.0 140 2006-03-12 00:00:00.000 200.0 122 2006-03-13 00:00:00.000 50.0 128 2006-03-13 00:00:00.000 60.0 131 2006-03-13 00:00:00.000 10.0 140 2006-03-13 00:00:00.000 20.0 123 2006-03-14 00:00:00.000 12.0 128 2006-03-14 00:00:00.000 70.0 131 2006-03-14 00:00:00.000 50.0 140 2006-03-14 00:00:00.000 310.0 128 2006-03-15 00:00:00.000 30.0 131 2006-03-15 00:00:00.000 18.0 (13 row(s) affected) 14 Odstranění dat z tabulky Odstraňte všechny záznamy v tabulce Platy DELETE FROM Platy; (0 row(s) affected) 15 5
Vložení dat do tabulky Přidejte do tabulky platy pro každého pracovníka za každý den plat ve výši jeho celkového výdělku Suma(počet kusů krát cena) INSERT INTO Platy (pl_pracovnik, pl_datum, pl_castka) SELECT p_pracovnik,p_datum, Sum(p_kusu*tp_cena) As Plat FROM prace INNER JOIN typyprace Server: MsgOn 547, p_typ=tp_nazev Level 16, State 1, Line 1 INSERT statement conflicted with COLUMN CHECK constraint 'CK_Platy'. The conflict occurred in GROUP BY p_pracovnik,p_datum; database 'prace', table 'Platy', column 'pl_castka'. The statement has been terminated. 16 Vložení dat do tabulky oprava Zjistěte, proč nebyly platy vloženy Nyní je vložení platů možné: (Je nutno INSERT odstranit INTO Platy omezení CK_Platy: ([pl_castka] (pl_pracovnik, > 10000): pl_datum, pl_castka) SELECT p_pracovnik,p_datum, ALTER TABLE Platy Sum(p_kusu*tp_cena) As Plat DROP FROM CONSTRAINT prace INNER CK_Platy; JOIN typyprace On p_typ=tp_nazev (13 row(s) affected) GROUP BY p_pracovnik,p_datum; 17 Určení záznamů bez podřízených Určete seznam pracovníků, kteří nemají žádnou práci SELECT Pracovnici.* FROM Pracovnici LEFT JOIN prace pr_osc pr_jmeno ON pr_osc=p_pracovnik 124 Ivanka Desátá-Jedenáctá 125 Jean-Dean Sikorski WHERE p_id IS 127 NULL; Jan Pavel I ----------- ----------------------------------------- 126 Patricia de Souza y Cachal de Brito 130 Orgoj Chorchoj 133 Jana Růžena Kostičkovitá 141 Ian z Glenyanu 152 Pavla Ospalá 153 Karel Ospalý (9 row(s) affected) 18 6
Vložený dotaz v definici sloupce Pro každého pracovníka určete počet prací pr_osc pr_jmeno Počet SELECT *, 122 Jan Kvákal 123 Patrik Svatý (SELECT COUNT(*) 2 1 124 Ivanka Desátá-Jedenáctá 0 125 Jean-Dean Sikorski 0 FROM prace 126 AS Patricia TMP de Souza y Cachal de Brito 0 127 Jan Pavel I 0 WHERE 128 TMP.p_pracovnik=Pracovnici.pr_OSC) Karla Osmá 4 130 131 AS Počet Orgoj Chorchoj Piotr Ivanovič Ustinovskij 0 3 133 Jana Růžena Kostičkovitá 0 140 Jan Evangelista Svatovítský 3 FROM Pracovnici; 141 Ian z Glenyanu 0 ----------- -------------------------------------------------- ------ 152 Pavla Ospalá 0 153 Karel Ospalý 0 (14 row(s) affected) 19 Vložený dotaz v definici sloupce Pro každého pracovníka určete počet dnů, kdy pracoval pr_osc pr_jmeno Počet SELECT ----------- *, ---------------------------------------- ----------- 122 Jan Kvákal 2 123 Patrik Svatý 1 (SELECT COUNT(DISTINCT p_datum) 124 Ivanka Desátá-Jedenáctá 0 125 Jean-Dean Sikorski 0 FROM prace 126 AS Patricia TMPde Souza y Cachal de Brito 0 127 Jan Pavel I 0 WHERE 128 TMP.p_pracovnik=Pracovnici.pr_OSC) Karla Osmá 4 130 131 AS Počet Orgoj Chorchoj Piotr Ivanovič Ustinovskij 0 3 133 Jana Růžena Kostičkovitá 0 140 Jan Evangelista Svatovítský 3 FROM Pracovnici; 141 Ian z Glenyanu 0 152 Pavla Ospalá 0 153 Karel Ospalý 0 (14 row(s) affected) 20 Konverze dat eliminace NULL Pro každého pracovníka určete počet kusů z tabulky prace, pokud dosud nepracoval, bude počet 0 pr_jmeno Počet SELECT ----------- pr_osc, ------------------------------------- pr_jmeno, ----- 122 Jan Kvákal 9.0 123 Patrik Svatý 12.0 COALESCE(SUM(p_kusu),0) AS Počet 124 Ivanka Desátá-Jedenáctá 0.0 125 Jean-Dean Sikorski 0.0 FROM pracovnici 126 Patricia de Souza y Cachal de Brito 0.0 127 Jan Pavel I 0.0 LEFT JOIN 128 prace Karla Osmá on pr_osc=p_pracovnik 18.0 130 Orgoj Chorchoj 131 Piotr Ivanovič Ustinovskij GROUP BY pr_osc, pr_jmeno; 0.0 24.0 133 Jana Růžena Kostičkovitá 0.0 140 Jan Evangelista Svatovítský 53.0 141 Ian z Glenyanu 0.0 152 Pavla Ospalá 0.0 153 Karel Ospalý 0.0 (14 row(s) affected) 21 7
Agregace - opakovaná Pro každého pracovníka zobrazte jeho osobní číslo, jméno a první a poslední den, ve kterém pracoval SELECT pr_osc, pr_jmeno, Min(p_datum) As prvni, Max(p_datum) As poslední FROM pr_osc pr_jmeno pracovnici INNER prvni JOIN praceposlední ON pr_osc=p_pracovnik GROUP BY pr_osc, pr_jmeno ORDER BY pr_jmeno; ------- ---------------------------- ----------------------- ----------------------- 140 Jan Evangelista Svatovítský 2006-03-12 00:00:00.000 2006-03-14 00:00:00.000 122 Jan Kvákal 2006-03-12 00:00:00.000 2006-03-13 00:00:00.000 128 Karla Osmá 2006-03-12 00:00:00.000 2006-03-15 00:00:00.000 123 Patrik Svatý 2006-03-14 00:00:00.000 2006-03-14 00:00:00.000 131 Piotr Ivanovič Ustinovskij 2006-03-13 00:00:00.000 2006-03-15 00:00:00.000 (5 row(s) affected) 22 Konverze dat Pro každého pracovníka zobrazte jeho osobní číslo, jméno a počet dnů mezi první a poslední prací SELECT pr_osc, pr_jmeno, CAST(Max(p_datum)-Min(p_datum) AS Integer) FROM pracovnici INNER JOIN prace pr_osc ON pr_osc=p_pracovnik pr_jmeno ----------- -------------------------------------------------- ----------- GROUP 140 Jan BY Evangelista pr_osc, Svatovítský pr_jmeno 2 122 Jan Kvákal 1 128 Karla Osmá 3 ORDER BY pr_jmeno; 123 Patrik Svatý 0 131 Piotr Ivanovič Ustinovskij 2 (5 row(s) affected) 23 Dávka využití kurzoru Vytvořte dávku, která vygeneruje pro tabulku typyprace dávku definicí dat tabulky DECLARE @nazev varchar(50), @popis varchar(8000), @cena money DECLARE listtypyprace CURSOR FORWARD_ONLY FOR SELECT [tp_nazev], [tp_popis], [tp_cena] FROM [prace].[dbo].[typyprace] OPEN listtypyprace FETCH NEXT FROM listtypyprace INTO @nazev, @popis, @cena INSERT INTO typyprace ([tp_nazev], [tp_popis], [tp_cena]) WHILE @@FETCH_STATUS = 0 VALUES ('hrdlení', 'jen mezi příbuznými', 25.00); INSERT INTO typyprace ([tp_nazev], [tp_popis], [tp_cena]) PRINT 'INSERT INTO typyprace ([tp_nazev], [tp_popis], VALUES [tp_cena])' ('kvákání', 'skupinové', 1000.00); PRINT 'VALUES (''' + @nazev + ''', ''' + @popis + INSERT ''', ' + CAST(@cena INTO typyprace as varchar) ([tp_nazev], + [tp_popis], [tp_cena]) ');' VALUES ('praní', 'každý kousek zvlášť', 10.00); FETCH NEXT FROM listtypyprace INSERT INTO typyprace ([tp_nazev], [tp_popis], [tp_cena]) INTO @nazev, @popis, @cena VALUES ('spaní', 'celou noc', 120.00); INSERT INTO typyprace ([tp_nazev], [tp_popis], [tp_cena]) CLOSE listtypyprace VALUES ('škudlení', 'každý okamžik', 1.00); DEALLOCATE listtypyprace 24 8
Uložená procedura Vytvořte uloženou proceduru VlozPraci, která převezme údaje o pracovníkovi, typu práce, počtu kusů a nepovinné datum (v tom případě vloží aktuální datum), zkontroluje existenci pracovníka a typu práce, vloží nový záznam do databáze a vrátí jeho ID (1 row(s) CREATE affected) PROCEDURE VlozPraci IF EXISTS (SELECT * FROM pracovnici WHERE pr_osc=@pracovnik) @pracovnik INT, 18 @typ VARCHAR(50), IF EXISTS (SELECT * FROM typyprace WHERE tp_nazev=@typ) pr_osc@kusu FLOAT, pr_jmeno ----------- @datum DATETIME ------------------------------------- = NULL, INSERT INTO prace Test 122 @ID INT OUTPUT Jan Kvákal (p_pracovnik, p_typ, p_kusu, p_datum) DECLARE @MyID INT 123 AS Patrik Svatý VALUES EXEC VlozPraci 124 DECLARE Ivanka @MyERRDesátá-Jedenáctá INT (@pracovnik, @typ, @kusu, @datum) @pracovnik=152, IF @datum IS NULL SELECT @MyERR = @@ERROR 125 Jean-Dean Sikorski @typ='praní', IF @MyERR!=0 TO err_handler 126 Patricia de Souza y Cachal de Brito @kusu=2, DECLARE @actdate as datetime SELECT @ID = @@IDENTITY 127 Jan Pavel I @ID=@MyID OUTPUT SET @actdate=getdate() 128 SET @datum=cast(cast(datepart(m, Karla Osmá PRINT @MyID @actdate) ELSE AS VARCHAR) + '/' + CAST(DATEPART(d, @actdate) AS 130 VARCHAR)+ Orgoj '/' + CAST(DATEPART(yy, Chorchoj @actdate) SELECT AS VARCHAR) @ID = 0 AS DATETIME) SELECT * FROM pracovnici 131 Piotr Ivanovič Ustinovskij 133 Jana Růžena KostičkovitáELSE 140 Jan Evangelista Svatovítský SELECT @ID = 0 141 Ian z Glenyanu RETURN 0 152 Pavla Ospalá err_handler: 153 Karel Ospalý SELECT @ID = -1 RETURN @MyERR (14 row(s) Informační affected) systémy 25 Spoušť Zdroj: Výsledek: ALTER TRIGGER pracemeniplaty ALTER TRIGGER ON [dbo].[prace] pracemeniplaty ON [dbo].[prace] FOR INSERT, UPDATE, FOR DELETE INSERT, UPDATE, DELETE AS AS -- zpracujeme Doplňte vložení nové DECLARE práce @pid INT, spoušť @pprac INT, @ptyp VARCHAR(50), o část @pkusu FLOAT, reagující @pdatum DATETIME, @pcena na money IF EXISTS (SELECT * -- FROM zpracujeme INSERTED) odstranění práce IF EXISTS (SELECT * FROM deleted) DECLARE @pid INT, @pprac INT, @ptyp VARCHAR(50), záznamu @pkusu FLOAT, @pdatum o DATETIME, práci @pcena money -- zjistíme kolik záznamů -- zjistíme je přidáno kolik záznamů je odstraněno DECLARE cpom CURSOR -- zpracujeme DECLARE cpom vložení CURSOR nové práce FOR IF FOR EXISTS (SELECT * FROM INSERTED) SELECT p_id, p_pracovnik, SELECT p_typ, p_id, p_kusu, p_pracovnik, p_datum p_typ, FROM p_kusu, inserted p_datum FROM deleted OPEN cpom -- OPEN zjistíme cpom kolik záznamů je přidáno -- vezmeme první nový DECLARE --záznam vezmeme cpom prvnícursor odstraněný záznam FETCH NEXT FROM cpom FOR FETCH NEXT FROM cpom INTO @pid, @pprac, @ptyp, SELECT INTO @pid, @pkusu, p_id, @pprac, p_pracovnik, @pdatum @ptyp, p_typ, @pkusu, p_kusu, @pdatum p_datum FROM inserted WHILE @@FETCH_STATUS WHILE OPEN cpom @@FETCH_STATUS = 0 = 0 -- vezmeme první nový záznam -- Určíme cenu vložené FETCH --práce Určíme NEXT cenu FROM odstraněné cpom práce SELECT @pcena = Max(tp_cena) INTO SELECT @pid, @pcena @pprac, FROM = typyprace Max(tp_cena) @ptyp, @pkusu, WHERE FROM @pdatum tp_nazev=@ptyp typyprace WHERE tp_nazev=@ptyp -- Pokud již tento pracovník WHILE -- Předpokládámě, v @@FETCH_STATUS daném dni pracoval, že vše řádně budeme = 0 funguje záznam a záznam upravovat, o platu jinak existuje musíme přidat nový IF EXISTS (SELECT * UPDATE FROM platy platy WHERE SET pl_castka=pl_castka-@pkusu*cast(@pcena pl_pracovnik=@pprac AND pl_datum=@pdatum) AS FLOAT) WHERE pl_pracovnik=@pprac AND pl_datum=@pdatum UPDATE platy SET pl_castka=pl_castka+@pkusu*cast(@pcena FETCH -- Určíme NEXT cenu FROM vložené cpom práce AS FLOAT) WHERE pl_pracovnik=@pprac AND pl_datum=@pdatum ELSE SELECT INTO @pid, @pcena @pprac, = Max(tp_cena) @ptyp, @pkusu, FROM @pdatum typyprace WHERE tp_nazev=@ptyp INSERT INTO platy(pl_pracovnik, -- Pokud již tento pl_datum, pracovník pl_castka) v daném VALUES dni pracoval, (@pprac, budeme @pdatum, záznam @pkusu*cast(@pcena upravovat, jinak musíme AS přidat FLOAT)) nový FETCH NEXT FROM CLOSE cpom IF EXISTS cpom(select * FROM platy WHERE pl_pracovnik=@pprac AND pl_datum=@pdatum) INTO @pid, @pprac, DEALLOCATE @ptyp, UPDATE @pkusu, platy cpom SET @pdatum pl_castka=pl_castka+@pkusu*cast(@pcena AS FLOAT) WHERE pl_pracovnik=@pprac AND pl_datum=@pdatum ELSE CLOSE cpom INSERT INTO platy(pl_pracovnik, pl_datum, pl_castka) VALUES (@pprac, @pdatum, @pkusu*cast(@pcena AS FLOAT)) DEALLOCATE cpom FETCH NEXT FROM cpom INTO @pid, @pprac, @ptyp, @pkusu, @pdatum CLOSE cpom DEALLOCATE cpom -- po skončení je možné, že některý záznam o platu se dostal na nulovou částku Informační DELETE FROM systémy Platy WHERE pl_castka=0 26 Kontrolní otázka Co se stane, pokud se změní cena některého typu práce? Odměny za tento typ práce nebudou odpovídat nové ceně. Důvodem je chyba v koncepci databáze tabulky typyprace obsahuje aktuální hodnoty, zatímco tabulky prace a platy obsahují historická data. Řešením je uložení aktuální ceny typu práce přímo k nově vložené práci, kde zůstane zachována i do budoucna. 27 9