intlddl.sql 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. /*
  2. * The contents of this file are subject to the Interbase Public
  3. * License Version 1.0 (the "License"); you may not use this file
  4. * except in compliance with the License. You may obtain a copy
  5. * of the License at http://www.Inprise.com/IPL.html
  6. *
  7. * Software distributed under the License is distributed on an
  8. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  9. * or implied. See the License for the specific language governing
  10. * rights and limitations under the License.
  11. *
  12. * The Original Code was created by Inprise Corporation
  13. * and its predecessors. Portions created by Inprise Corporation are
  14. * Copyright (C) Inprise Corporation.
  15. *
  16. * All Rights Reserved.
  17. * Contributor(s): ______________________________________.
  18. */
  19. /*CREATE DATABASE "intl_emp.fdb" DEFAULT CHARACTER SET ISO8859_1; */
  20. /** 18-July-1994: Clare Taylor: Created this file, intlddl.sql, from the
  21. ** empddl.sql file. It has been modified as shown below
  22. ** to create an international version of the example database.
  23. **
  24. ** Create a sample international employee database (intlemp.fdb).
  25. **
  26. ** This database keeps track of employees, departments, projects, and sales
  27. ** for a small company and uses ISO8859_1 for the DEFAULT CHARACTER SET.
  28. **
  29. ** International changes to this file:
  30. **
  31. ** - DOMAIN lastname: increased field size to 25 from 20.
  32. ** - CUSTOMER.CUSTOMER field: increased the field size to 40. required
  33. ** for long German and French company names.
  34. ** - CUSTOMER.ADDRESS1 and 2: increased from 30 to 40 chars.
  35. ** - Added 4 sorting stored procedures--may be changed in next build.
  36. **/
  37. /* set echo; */
  38. /*
  39. * Define domains.
  40. */
  41. CREATE DOMAIN firstname AS VARCHAR(15) COLLATE FR_FR;
  42. CREATE DOMAIN lastname AS VARCHAR(25) COLLATE FR_FR;
  43. CREATE DOMAIN phonenumber AS VARCHAR(20);
  44. CREATE DOMAIN countryname AS VARCHAR(15);
  45. CREATE DOMAIN addressline AS VARCHAR(40);
  46. CREATE DOMAIN empno
  47. AS SMALLINT;
  48. CREATE DOMAIN deptno
  49. AS CHAR(3) CHARACTER SET ASCII
  50. CHECK (VALUE = '000' OR (VALUE > '0' AND VALUE <= '999') OR VALUE IS NULL);
  51. CREATE DOMAIN projno
  52. AS CHAR(5) CHARACTER SET ASCII
  53. CHECK (VALUE = UPPER (VALUE));
  54. CREATE DOMAIN custno
  55. AS INTEGER
  56. CHECK (VALUE > 1000);
  57. /* must begin with a letter */
  58. CREATE DOMAIN jobcode
  59. AS VARCHAR(5) CHARACTER SET ASCII
  60. CHECK (VALUE > '99999');
  61. CREATE DOMAIN jobgrade
  62. AS SMALLINT
  63. CHECK (VALUE BETWEEN 0 AND 6);
  64. /* salary is in any currency type */
  65. CREATE DOMAIN salary
  66. AS NUMERIC(10,2)
  67. DEFAULT 0
  68. CHECK (VALUE > 0);
  69. /* budget is in US dollars */
  70. CREATE DOMAIN budget
  71. AS DECIMAL(12,2)
  72. DEFAULT 50000
  73. CHECK (VALUE > 10000 AND VALUE <= 2000000);
  74. CREATE DOMAIN prodtype
  75. AS VARCHAR(12)
  76. DEFAULT 'software' NOT NULL
  77. CHECK (VALUE IN ('software', 'hardware', 'other', 'N/A'));
  78. CREATE DOMAIN PONUMBER
  79. AS CHAR(8)
  80. CHECK (VALUE STARTING WITH 'V');
  81. /*
  82. * Create generators.
  83. */
  84. CREATE GENERATOR emp_no_gen;
  85. CREATE GENERATOR cust_no_gen;
  86. SET GENERATOR cust_no_gen to 1000;
  87. COMMIT;
  88. /*
  89. * Create tables.
  90. */
  91. /*
  92. * Country name, currency type.
  93. */
  94. CREATE TABLE country
  95. (
  96. country COUNTRYNAME NOT NULL PRIMARY KEY,
  97. currency VARCHAR(10) NOT NULL
  98. );
  99. /*
  100. * Job id, job title, minimum and maximum salary, job description,
  101. * and required languages.
  102. *
  103. * A job is defined by a multiple key, consisting of a job_code
  104. * (a 5-letter job abbreviation), a job grade, and a country name
  105. * indicating the salary currency type.
  106. *
  107. * The salary range is expressed in the appropriate country's currency.
  108. *
  109. * The job requirement is a text blob.
  110. *
  111. * The job may also require some knowledge of foreign languages,
  112. * stored in a character array.
  113. */
  114. CREATE TABLE job
  115. (
  116. job_code JOBCODE NOT NULL,
  117. job_grade JOBGRADE NOT NULL,
  118. job_country COUNTRYNAME NOT NULL,
  119. job_title VARCHAR(25) NOT NULL,
  120. min_salary SALARY NOT NULL,
  121. max_salary SALARY NOT NULL,
  122. job_requirement BLOB(400,1),
  123. language_req VARCHAR(15) [5],
  124. PRIMARY KEY (job_code, job_grade, job_country),
  125. FOREIGN KEY (job_country) REFERENCES country (country),
  126. CHECK (min_salary < max_salary)
  127. );
  128. CREATE ASCENDING INDEX minsalx ON job (job_country, min_salary);
  129. CREATE DESCENDING INDEX maxsalx ON job (job_country, max_salary);
  130. /*
  131. * Department number, name, head department, manager id,
  132. * budget, location, department phone number.
  133. *
  134. * Each department is a sub-department in some department, determined
  135. * by head_dept. The head of this tree is the company.
  136. * This information is used to produce a company organization chart.
  137. *
  138. * Departments have managers; however, manager id can be null to allow
  139. * for temporary situations where a manager needs to be hired.
  140. *
  141. * Budget is allocated in U.S. dollars for all departments.
  142. *
  143. * Foreign key mngr_no is added after the employee table is created,
  144. * using 'alter table'.
  145. */
  146. CREATE TABLE department
  147. (
  148. dept_no DEPTNO NOT NULL,
  149. department VARCHAR(25) NOT NULL UNIQUE,
  150. head_dept DEPTNO,
  151. mngr_no EMPNO,
  152. budget BUDGET,
  153. location VARCHAR(15),
  154. phone_no PHONENUMBER DEFAULT '555-1234',
  155. PRIMARY KEY (dept_no),
  156. FOREIGN KEY (head_dept) REFERENCES department (dept_no)
  157. );
  158. CREATE DESCENDING INDEX budgetx ON department (budget);
  159. /*
  160. * Employee id, name, phone extension, date of hire, department id,
  161. * job and salary information.
  162. *
  163. * Salary can be entered in any country's currency.
  164. * Therefore, some of the salaries can appear magnitudes larger than others,
  165. * depending on the currency type. Ex. Italian lira vs. U.K. pound.
  166. * The currency type is determined by the country code.
  167. *
  168. * job_code, job_grade, and job_country reference employee's job information,
  169. * illustrating two tables related by referential constraints on multiple
  170. * columns.
  171. *
  172. * The employee salary is verified to be in the correct salary range
  173. * for the given job title.
  174. */
  175. CREATE TABLE employee
  176. (
  177. emp_no EMPNO NOT NULL,
  178. first_name FIRSTNAME NOT NULL,
  179. last_name LASTNAME NOT NULL,
  180. phone_ext VARCHAR(4),
  181. hire_date TIMESTAMP DEFAULT 'NOW' NOT NULL,
  182. dept_no DEPTNO NOT NULL,
  183. job_code JOBCODE NOT NULL,
  184. job_grade JOBGRADE NOT NULL,
  185. job_country COUNTRYNAME NOT NULL,
  186. salary SALARY NOT NULL,
  187. full_name COMPUTED BY (last_name || ', ' || first_name),
  188. PRIMARY KEY (emp_no),
  189. FOREIGN KEY (dept_no) REFERENCES
  190. department (dept_no),
  191. FOREIGN KEY (job_code, job_grade, job_country) REFERENCES
  192. job (job_code, job_grade, job_country),
  193. CHECK ( salary >= (SELECT min_salary FROM job WHERE
  194. job.job_code = employee.job_code AND
  195. job.job_grade = employee.job_grade AND
  196. job.job_country = employee.job_country) AND
  197. salary <= (SELECT max_salary FROM job WHERE
  198. job.job_code = employee.job_code AND
  199. job.job_grade = employee.job_grade AND
  200. job.job_country = employee.job_country))
  201. );
  202. CREATE INDEX namex ON employee (last_name, first_name);
  203. CREATE VIEW phone_list AS SELECT
  204. emp_no, first_name, last_name, phone_ext, location, phone_no
  205. FROM employee, department
  206. WHERE employee.dept_no = department.dept_no;
  207. COMMIT;
  208. SET TERM !! ;
  209. CREATE TRIGGER set_emp_no FOR employee
  210. BEFORE INSERT AS
  211. BEGIN
  212. new.emp_no = gen_id(emp_no_gen, 1);
  213. END !!
  214. SET TERM ; !!
  215. /*
  216. * Add an additional constraint to department: check manager numbers
  217. * in the employee table.
  218. */
  219. ALTER TABLE department ADD FOREIGN KEY (mngr_no) REFERENCES employee (emp_no);
  220. /*
  221. * Project id, project name, description, project team leader,
  222. * and product type.
  223. *
  224. * Project description is a text blob.
  225. */
  226. CREATE TABLE project
  227. (
  228. proj_id PROJNO NOT NULL,
  229. proj_name VARCHAR(20) NOT NULL UNIQUE,
  230. proj_desc BLOB(800,1),
  231. team_leader EMPNO,
  232. product PRODTYPE,
  233. PRIMARY KEY (proj_id),
  234. FOREIGN KEY (team_leader) REFERENCES employee (emp_no)
  235. );
  236. CREATE UNIQUE INDEX prodtypex ON project (product, proj_name);
  237. /*
  238. * Employee id, project id, employee's project duties.
  239. *
  240. * Employee duties is a text blob.
  241. */
  242. CREATE TABLE employee_project
  243. (
  244. emp_no EMPNO NOT NULL,
  245. proj_id PROJNO NOT NULL,
  246. PRIMARY KEY (emp_no, proj_id),
  247. FOREIGN KEY (emp_no) REFERENCES employee (emp_no),
  248. FOREIGN KEY (proj_id) REFERENCES project (proj_id)
  249. );
  250. /*
  251. * Fiscal year, project id, department id, projected head count by
  252. * fiscal quarter, projected budget.
  253. *
  254. * Tracks head count and budget planning by project by department.
  255. *
  256. * Quarterly head count is an array of integers.
  257. */
  258. CREATE TABLE proj_dept_budget
  259. (
  260. fiscal_year INTEGER NOT NULL CHECK (FISCAL_YEAR >= 1993),
  261. proj_id PROJNO NOT NULL,
  262. dept_no DEPTNO NOT NULL,
  263. quart_head_cnt INTEGER [4],
  264. projected_budget BUDGET,
  265. PRIMARY KEY (fiscal_year, proj_id, dept_no),
  266. FOREIGN KEY (dept_no) REFERENCES department (dept_no),
  267. FOREIGN KEY (proj_id) REFERENCES project (proj_id)
  268. );
  269. /*
  270. * Employee number, salary change date, updater's user id, old salary,
  271. * and percent change between old and new salary.
  272. */
  273. CREATE TABLE salary_history
  274. (
  275. emp_no EMPNO NOT NULL,
  276. change_date TIMESTAMP DEFAULT 'NOW' NOT NULL,
  277. updater_id VARCHAR(20) NOT NULL,
  278. old_salary SALARY NOT NULL,
  279. percent_change DOUBLE PRECISION
  280. DEFAULT 0
  281. NOT NULL
  282. CHECK (percent_change between -50 and 50),
  283. new_salary COMPUTED BY
  284. (old_salary + old_salary * percent_change / 100),
  285. PRIMARY KEY (emp_no, change_date, updater_id),
  286. FOREIGN KEY (emp_no) REFERENCES employee (emp_no)
  287. );
  288. CREATE INDEX updaterx ON salary_history (updater_id);
  289. CREATE DESCENDING INDEX changex ON salary_history (change_date);
  290. COMMIT;
  291. SET TERM !! ;
  292. CREATE TRIGGER save_salary_change FOR employee
  293. AFTER UPDATE AS
  294. BEGIN
  295. IF (old.salary <> new.salary) THEN
  296. INSERT INTO salary_history
  297. (emp_no, change_date, updater_id, old_salary, percent_change)
  298. VALUES (
  299. old.emp_no,
  300. 'NOW',
  301. user,
  302. old.salary,
  303. (new.salary - old.salary) * 100 / old.salary);
  304. END !!
  305. SET TERM ; !!
  306. COMMIT;
  307. /*
  308. * Customer id, customer name, contact first and last names,
  309. * phone number, address lines, city, state or province, country,
  310. * postal code or zip code, and customer status.
  311. */
  312. CREATE TABLE customer
  313. (
  314. cust_no CUSTNO NOT NULL,
  315. customer VARCHAR(35) NOT NULL COLLATE FR_FR,
  316. contact_first FIRSTNAME,
  317. contact_last LASTNAME,
  318. phone_no PHONENUMBER,
  319. address_line1 ADDRESSLINE,
  320. address_line2 ADDRESSLINE,
  321. city VARCHAR(25),
  322. state_province VARCHAR(15),
  323. country COUNTRYNAME,
  324. postal_code VARCHAR(12),
  325. on_hold CHAR
  326. DEFAULT NULL
  327. CHECK (on_hold IS NULL OR on_hold = '*'),
  328. PRIMARY KEY (cust_no),
  329. FOREIGN KEY (country) REFERENCES country (country)
  330. );
  331. CREATE INDEX custnamex ON customer (customer);
  332. CREATE INDEX custregion ON customer (country, city);
  333. SET TERM !! ;
  334. CREATE TRIGGER set_cust_no FOR customer
  335. BEFORE INSERT AS
  336. BEGIN
  337. new.cust_no = gen_id(cust_no_gen, 1);
  338. END !!
  339. SET TERM ; !!
  340. COMMIT;
  341. /*
  342. * Purchase order number, customer id, sales representative, order status,
  343. * order date, date shipped, date need to ship by, payment received flag,
  344. * quantity ordered, total order value, type of product ordered,
  345. * any percent discount offered.
  346. *
  347. * Tracks customer orders.
  348. *
  349. * sales_rep is the ID of the employee handling the sale.
  350. *
  351. * Number of days passed since the order date is a computed field.
  352. *
  353. * Several checks are performed on this table, among them:
  354. * - A sale order must have a status: open, shipped, waiting.
  355. * - The ship date must be entered, if order status is 'shipped'.
  356. * - New orders can't be shipped to customers with 'on_hold' status.
  357. * - Sales rep
  358. */
  359. CREATE TABLE sales
  360. (
  361. po_number PONUMBER NOT NULL,
  362. cust_no CUSTNO NOT NULL,
  363. sales_rep EMPNO,
  364. order_status VARCHAR(7)
  365. DEFAULT 'new'
  366. NOT NULL
  367. CHECK (order_status in
  368. ('new', 'open', 'shipped', 'waiting')),
  369. order_date TIMESTAMP
  370. DEFAULT 'NOW'
  371. NOT NULL,
  372. ship_date TIMESTAMP
  373. CHECK (ship_date >= order_date OR ship_date IS NULL),
  374. date_needed TIMESTAMP
  375. CHECK (date_needed > order_date OR date_needed IS NULL),
  376. paid CHAR
  377. DEFAULT 'n'
  378. CHECK (paid in ('y', 'n')),
  379. qty_ordered INTEGER
  380. DEFAULT 1
  381. NOT NULL
  382. CHECK (qty_ordered >= 1),
  383. total_value DECIMAL(9,2)
  384. NOT NULL
  385. CHECK (total_value >= 0),
  386. discount FLOAT
  387. DEFAULT 0
  388. NOT NULL
  389. CHECK (discount >= 0 AND discount <= 1),
  390. item_type PRODTYPE,
  391. aged COMPUTED BY
  392. (ship_date - order_date),
  393. PRIMARY KEY (po_number),
  394. FOREIGN KEY (cust_no) REFERENCES customer (cust_no),
  395. FOREIGN KEY (sales_rep) REFERENCES employee (emp_no),
  396. CHECK (NOT (order_status = 'shipped' AND ship_date IS NULL)),
  397. CHECK (NOT (order_status = 'shipped' AND
  398. EXISTS (SELECT on_hold FROM customer
  399. WHERE customer.cust_no = sales.cust_no
  400. AND customer.on_hold = '*')))
  401. );
  402. CREATE INDEX needx ON sales (date_needed);
  403. CREATE INDEX salestatx ON sales (order_status, paid);
  404. CREATE DESCENDING INDEX qtyx ON sales (item_type, qty_ordered);
  405. SET TERM !! ;
  406. CREATE TRIGGER post_new_order FOR sales
  407. AFTER INSERT AS
  408. BEGIN
  409. POST_EVENT 'new_order';
  410. END !!
  411. SET TERM ; !!
  412. COMMIT;
  413. /****************************************************************************
  414. *
  415. * Create stored procedures.
  416. *
  417. *****************************************************************************/
  418. SET TERM !! ;
  419. /*
  420. * Get employee's projects.
  421. *
  422. * Parameters:
  423. * employee number
  424. * Returns:
  425. * project id
  426. */
  427. CREATE PROCEDURE get_emp_proj (emp_no SMALLINT)
  428. RETURNS (proj_id CHAR(5)) AS
  429. BEGIN
  430. FOR SELECT proj_id
  431. FROM employee_project
  432. WHERE emp_no = :emp_no
  433. INTO :proj_id
  434. DO
  435. SUSPEND;
  436. END !!
  437. /*
  438. * Add an employee to a project.
  439. *
  440. * Parameters:
  441. * employee number
  442. * project id
  443. * Returns:
  444. * --
  445. */
  446. CREATE EXCEPTION unknown_emp_id 'Invalid employee number or project id.' !!
  447. CREATE PROCEDURE add_emp_proj (emp_no SMALLINT, proj_id CHAR(5)) AS
  448. BEGIN
  449. BEGIN
  450. INSERT INTO employee_project (emp_no, proj_id) VALUES (:emp_no, :proj_id);
  451. WHEN SQLCODE -530 DO
  452. EXCEPTION unknown_emp_id;
  453. END
  454. SUSPEND;
  455. END !!
  456. /*
  457. * Select one row.
  458. *
  459. * Compute total, average, smallest, and largest department budget.
  460. *
  461. * Parameters:
  462. * department id
  463. * Returns:
  464. * total budget
  465. * average budget
  466. * min budget
  467. * max budget
  468. */
  469. CREATE PROCEDURE sub_tot_budget (head_dept CHAR(3))
  470. RETURNS (tot_budget DECIMAL(12, 2), avg_budget DECIMAL(12, 2),
  471. min_budget DECIMAL(12, 2), max_budget DECIMAL(12, 2))
  472. AS
  473. BEGIN
  474. SELECT SUM(budget), AVG(budget), MIN(budget), MAX(budget)
  475. FROM department
  476. WHERE head_dept = :head_dept
  477. INTO :tot_budget, :avg_budget, :min_budget, :max_budget;
  478. SUSPEND;
  479. END !!
  480. /*
  481. * Delete an employee.
  482. *
  483. * Parameters:
  484. * employee number
  485. * Returns:
  486. * --
  487. */
  488. CREATE EXCEPTION reassign_sales
  489. 'Reassign the sales records before deleting this employee.' !!
  490. CREATE PROCEDURE delete_employee (emp_num INTEGER)
  491. AS
  492. DECLARE VARIABLE any_sales INTEGER;
  493. BEGIN
  494. any_sales = 0;
  495. /*
  496. * If there are any sales records referencing this employee,
  497. * can't delete the employee until the sales are re-assigned
  498. * to another employee or changed to NULL.
  499. */
  500. SELECT count(po_number)
  501. FROM sales
  502. WHERE sales_rep = :emp_num
  503. INTO :any_sales;
  504. IF (any_sales > 0) THEN
  505. BEGIN
  506. EXCEPTION reassign_sales;
  507. SUSPEND;
  508. END
  509. /*
  510. * If the employee is a manager, update the department.
  511. */
  512. UPDATE department
  513. SET mngr_no = NULL
  514. WHERE mngr_no = :emp_num;
  515. /*
  516. * If the employee is a project leader, update project.
  517. */
  518. UPDATE project
  519. SET team_leader = NULL
  520. WHERE team_leader = :emp_num;
  521. /*
  522. * Delete the employee from any projects.
  523. */
  524. DELETE FROM employee_project
  525. WHERE emp_no = :emp_num;
  526. /*
  527. * Delete old salary records.
  528. */
  529. DELETE FROM salary_history
  530. WHERE emp_no = :emp_num;
  531. /*
  532. * Delete the employee.
  533. */
  534. DELETE FROM employee
  535. WHERE emp_no = :emp_num;
  536. SUSPEND;
  537. END !!
  538. /*
  539. * Recursive procedure.
  540. *
  541. * Compute the sum of all budgets for a department and all the
  542. * departments under it.
  543. *
  544. * Parameters:
  545. * department id
  546. * Returns:
  547. * total budget
  548. */
  549. CREATE PROCEDURE dept_budget (dno CHAR(3))
  550. RETURNS (tot decimal(12,2)) AS
  551. DECLARE VARIABLE sumb DECIMAL(12, 2);
  552. DECLARE VARIABLE rdno CHAR(3);
  553. DECLARE VARIABLE cnt INTEGER;
  554. BEGIN
  555. tot = 0;
  556. SELECT budget FROM department WHERE dept_no = :dno INTO :tot;
  557. SELECT count(budget) FROM department WHERE head_dept = :dno INTO :cnt;
  558. IF (cnt = 0) THEN
  559. SUSPEND;
  560. FOR SELECT dept_no
  561. FROM department
  562. WHERE head_dept = :dno
  563. INTO :rdno
  564. DO
  565. BEGIN
  566. EXECUTE PROCEDURE dept_budget :rdno RETURNING_VALUES :sumb;
  567. tot = tot + sumb;
  568. END
  569. SUSPEND;
  570. END !!
  571. /*
  572. * Display an org-chart.
  573. *
  574. * Parameters:
  575. * --
  576. * Returns:
  577. * parent department
  578. * department name
  579. * department manager
  580. * manager's job title
  581. * number of employees in the department
  582. */
  583. CREATE PROCEDURE org_chart
  584. RETURNS (head_dept CHAR(25), department CHAR(25),
  585. mngr_name CHAR(20), title CHAR(5), emp_cnt INTEGER)
  586. AS
  587. DECLARE VARIABLE mngr_no INTEGER;
  588. DECLARE VARIABLE dno CHAR(3);
  589. BEGIN
  590. FOR SELECT h.department, d.department, d.mngr_no, d.dept_no
  591. FROM department d
  592. LEFT OUTER JOIN department h ON d.head_dept = h.dept_no
  593. ORDER BY d.dept_no
  594. INTO :head_dept, :department, :mngr_no, :dno
  595. DO
  596. BEGIN
  597. IF (:mngr_no IS NULL) THEN
  598. BEGIN
  599. mngr_name = '--TBH--';
  600. title = '';
  601. END
  602. ELSE
  603. SELECT full_name, job_code
  604. FROM employee
  605. WHERE emp_no = :mngr_no
  606. INTO :mngr_name, :title;
  607. SELECT COUNT(emp_no)
  608. FROM employee
  609. WHERE dept_no = :dno
  610. INTO :emp_cnt;
  611. SUSPEND;
  612. END
  613. END !!
  614. /*
  615. * Generate a 6-line mailing label for a customer.
  616. * Some of the lines may be blank.
  617. *
  618. * Parameters:
  619. * customer number
  620. * Returns:
  621. * 6 address lines
  622. */
  623. CREATE PROCEDURE mail_label (cust_no INTEGER)
  624. RETURNS (line1 CHAR(40), line2 CHAR(40), line3 CHAR(40),
  625. line4 CHAR(40), line5 CHAR(40), line6 CHAR(40))
  626. AS
  627. DECLARE VARIABLE customer VARCHAR(25);
  628. DECLARE VARIABLE first_name VARCHAR(15);
  629. DECLARE VARIABLE last_name VARCHAR(20);
  630. DECLARE VARIABLE addr1 VARCHAR(30);
  631. DECLARE VARIABLE addr2 VARCHAR(30);
  632. DECLARE VARIABLE city VARCHAR(25);
  633. DECLARE VARIABLE state VARCHAR(15);
  634. DECLARE VARIABLE country VARCHAR(15);
  635. DECLARE VARIABLE postcode VARCHAR(12);
  636. DECLARE VARIABLE cnt INTEGER;
  637. BEGIN
  638. line1 = '';
  639. line2 = '';
  640. line3 = '';
  641. line4 = '';
  642. line5 = '';
  643. line6 = '';
  644. SELECT customer, contact_first, contact_last, address_line1,
  645. address_line2, city, state_province, country, postal_code
  646. FROM CUSTOMER
  647. WHERE cust_no = :cust_no
  648. INTO :customer, :first_name, :last_name, :addr1, :addr2,
  649. :city, :state, :country, :postcode;
  650. IF (customer IS NOT NULL) THEN
  651. line1 = customer;
  652. IF (first_name IS NOT NULL) THEN
  653. line2 = first_name || ' ' || last_name;
  654. ELSE
  655. line2 = last_name;
  656. IF (addr1 IS NOT NULL) THEN
  657. line3 = addr1;
  658. IF (addr2 IS NOT NULL) THEN
  659. line4 = addr2;
  660. IF (country = 'USA') THEN
  661. BEGIN
  662. IF (city IS NOT NULL) THEN
  663. line5 = city || ', ' || state || ' ' || postcode;
  664. ELSE
  665. line5 = state || ' ' || postcode;
  666. END
  667. ELSE
  668. BEGIN
  669. IF (city IS NOT NULL) THEN
  670. line5 = city || ', ' || state;
  671. ELSE
  672. line5 = state;
  673. line6 = country || ' ' || postcode;
  674. END
  675. SUSPEND;
  676. END !!
  677. /*
  678. * Ship a sales order.
  679. * First, check if the order is already shipped, if the customer
  680. * is on hold, or if the customer has an overdue balance.
  681. *
  682. * Parameters:
  683. * purchase order number
  684. * Returns:
  685. * --
  686. *
  687. */
  688. CREATE EXCEPTION order_already_shipped 'Order status is "shipped."' !!
  689. CREATE EXCEPTION customer_on_hold 'This customer is on hold.' !!
  690. CREATE EXCEPTION customer_check 'Overdue balance -- can not ship.' !!
  691. CREATE PROCEDURE ship_order (po_num CHAR(8))
  692. AS
  693. DECLARE VARIABLE ord_stat CHAR(7);
  694. DECLARE VARIABLE hold_stat CHAR(1);
  695. DECLARE VARIABLE cust_no INTEGER;
  696. DECLARE VARIABLE any_po CHAR(8);
  697. BEGIN
  698. SELECT s.order_status, c.on_hold, c.cust_no
  699. FROM sales s, customer c
  700. WHERE po_number = :po_num
  701. AND s.cust_no = c.cust_no
  702. INTO :ord_stat, :hold_stat, :cust_no;
  703. /* This purchase order has been already shipped. */
  704. IF (ord_stat = 'shipped') THEN
  705. BEGIN
  706. EXCEPTION order_already_shipped;
  707. SUSPEND;
  708. END
  709. /* Customer is on hold. */
  710. ELSE IF (hold_stat = '*') THEN
  711. BEGIN
  712. EXCEPTION customer_on_hold;
  713. SUSPEND;
  714. END
  715. /*
  716. * If there is an unpaid balance on orders shipped over 2 months ago,
  717. * put the customer on hold.
  718. */
  719. FOR SELECT po_number
  720. FROM sales
  721. WHERE cust_no = :cust_no
  722. AND order_status = 'shipped'
  723. AND paid = 'n'
  724. AND ship_date < CAST('NOW' AS TIMESTAMP) - 60
  725. INTO :any_po
  726. DO
  727. BEGIN
  728. EXCEPTION customer_check;
  729. UPDATE customer
  730. SET on_hold = '*'
  731. WHERE cust_no = :cust_no;
  732. SUSPEND;
  733. END
  734. /*
  735. * Ship the order.
  736. */
  737. UPDATE sales
  738. SET order_status = 'shipped', ship_date = 'NOW'
  739. WHERE po_number = :po_num;
  740. SUSPEND;
  741. END !!
  742. CREATE PROCEDURE show_langs (code VARCHAR(5), grade SMALLINT, cty VARCHAR(15))
  743. RETURNS (languages VARCHAR(15))
  744. AS
  745. DECLARE VARIABLE i INTEGER;
  746. BEGIN
  747. i = 1;
  748. WHILE (i <= 5) DO
  749. BEGIN
  750. SELECT language_req[:i] FROM joB
  751. WHERE ((job_code = :code) AND (job_grade = :grade) AND (job_country = :cty)
  752. AND (language_req IS NOT NULL))
  753. INTO :languages;
  754. IF (languages = ' ') THEN /* Prints 'NULL' instead of blanks */
  755. languages = 'NULL';
  756. i = i +1;
  757. SUSPEND;
  758. END
  759. END!!
  760. CREATE PROCEDURE all_langs RETURNS
  761. (code VARCHAR(5), grade VARCHAR(5),
  762. country VARCHAR(15), LANG VARCHAR(15)) AS
  763. BEGIN
  764. FOR SELECT job_code, job_grade, job_country FROM job
  765. INTO :code, :grade, :country
  766. DO
  767. BEGIN
  768. FOR SELECT languages FROM show_langs
  769. (:code, :grade, :country) INTO :lang DO
  770. SUSPEND;
  771. /* Put nice separators between rows */
  772. code = '=====';
  773. grade = '=====';
  774. country = '===============';
  775. lang = '==============';
  776. SUSPEND;
  777. END
  778. END!!
  779. SET TERM ; !!
  780. /*******************************************************************
  781. * Set of procedures to demonstrate sorts based on different
  782. * collations.
  783. *******************************************************************/
  784. SET TERM !! ;
  785. CREATE PROCEDURE FRENCH_CUST_SORT
  786. RETURNS (customer VARCHAR(40), city VARCHAR(25), country VARCHAR(15))
  787. AS
  788. BEGIN
  789. FOR SELECT customer, city, country
  790. FROM customer ORDER BY customer
  791. INTO :customer, :city, :country
  792. DO
  793. SUSPEND;
  794. END !!
  795. CREATE PROCEDURE GERMAN_CUST_SORT
  796. RETURNS (customer VARCHAR(40), city VARCHAR(25), country VARCHAR(15))
  797. AS
  798. BEGIN
  799. FOR SELECT customer, city, country
  800. FROM customer ORDER BY customer COLLATE DE_DE
  801. INTO :customer, :city, :country
  802. DO
  803. SUSPEND;
  804. END !!
  805. CREATE PROCEDURE NORWAY_CUST_SORT
  806. RETURNS (customer VARCHAR(40), city VARCHAR(25), country VARCHAR(15))
  807. AS
  808. BEGIN
  809. FOR SELECT customer, city, country
  810. FROM customer ORDER BY customer COLLATE NO_NO
  811. INTO :customer, :city, :country
  812. DO
  813. SUSPEND;
  814. END !!
  815. SET TERM ; !!
  816. /*--------------------------------------------------------------
  817. ** Function definitions for example database
  818. ** Functions not supported for international, maybe in next build
  819. **--------------------------------------------------------------
  820. */
  821. /* Privileges */
  822. GRANT ALL PRIVILEGES ON country TO PUBLIC WITH GRANT OPTION;
  823. GRANT ALL PRIVILEGES ON job TO PUBLIC WITH GRANT OPTION;
  824. GRANT ALL PRIVILEGES ON department TO PUBLIC WITH GRANT OPTION;
  825. GRANT ALL PRIVILEGES ON employee TO PUBLIC WITH GRANT OPTION;
  826. GRANT ALL PRIVILEGES ON phone_list TO PUBLIC WITH GRANT OPTION;
  827. GRANT ALL PRIVILEGES ON project TO PUBLIC WITH GRANT OPTION;
  828. GRANT ALL PRIVILEGES ON employee_project TO PUBLIC WITH GRANT OPTION;
  829. GRANT ALL PRIVILEGES ON proj_dept_budget TO PUBLIC WITH GRANT OPTION;
  830. GRANT ALL PRIVILEGES ON salary_history TO PUBLIC WITH GRANT OPTION;
  831. GRANT ALL PRIVILEGES ON customer TO PUBLIC WITH GRANT OPTION;
  832. GRANT ALL PRIVILEGES ON sales TO PUBLIC WITH GRANT OPTION;
  833. GRANT EXECUTE ON PROCEDURE get_emp_proj TO PUBLIC WITH GRANT OPTION;
  834. GRANT EXECUTE ON PROCEDURE add_emp_proj TO PUBLIC WITH GRANT OPTION;
  835. GRANT EXECUTE ON PROCEDURE sub_tot_budget TO PUBLIC WITH GRANT OPTION;
  836. GRANT EXECUTE ON PROCEDURE delete_employee TO PUBLIC WITH GRANT OPTION;
  837. GRANT EXECUTE ON PROCEDURE dept_budget TO PUBLIC WITH GRANT OPTION;
  838. GRANT EXECUTE ON PROCEDURE org_chart TO PUBLIC WITH GRANT OPTION;
  839. GRANT EXECUTE ON PROCEDURE mail_label TO PUBLIC WITH GRANT OPTION;
  840. GRANT EXECUTE ON PROCEDURE ship_order TO PUBLIC WITH GRANT OPTION;
  841. GRANT EXECUTE ON PROCEDURE show_langs TO PUBLIC WITH GRANT OPTION;
  842. GRANT EXECUTE ON PROCEDURE all_langs TO PUBLIC WITH GRANT OPTION;
  843. GRANT EXECUTE ON PROCEDURE french_cust_sort TO PUBLIC WITH GRANT OPTION;
  844. GRANT EXECUTE ON PROCEDURE german_cust_sort TO PUBLIC WITH GRANT OPTION;
  845. GRANT EXECUTE ON PROCEDURE norway_cust_sort TO PUBLIC WITH GRANT OPTION;