Grundidee: PSP
–
Internet-Seiten mit dynamischer Präsentation von Inhalten durch Einsatz von PL/SQL-Anweisungen
–
Server-Side Scripting (Generierung der Seiten im DB-Server - nicht im Webserver)
–
Basiert auf PL/SQL Web Toolkit
–
Bestandteil von Oracle Application Server (OAS) und Oracle WebDB
–
Einbindung dynamischer Inhalte durch PL/SQL-
Skripte, durch spezielle Tags gekennzeichnet
Einordnung in Oracle Application
Server
Vorteile von PSP
Trennung von Anwendungs- und Präsentationslogik
– HTML-Anweisungen und PL/SQL Code separat
– Abgrenzung durch PL/SQL-spezifische Tags
Leichte Erlernbarkeit
Einfacher Zugriff auf Daten der Datenbank
Ausführung im Server
Verbindung mit anderen Skriptsprachen möglich
– z.B. Javascript oder Visual Basic-Script (zur Prüfung von Benutzereingaben)
– nicht kombinierbar mit anderen serverseitigen Scripting-techniken
Web Toolkit vs. PSP
CREATE OR REPLACE PROCEDURE home_page AS BEGIN
htp.htmlOpen;
htp.headOpen;
htp.title(‘My home page‘);
htp.headClose;
htp.bodyOpen;
htp.print (‘This is the home page of ‘|| user ||‘
generated on ‘ || sysdate || ‘.‘);
htp.bodyClose;
htp.htmlClose;
END;
CREATE OR REPLACE PROCEDURE home_page AS BEGIN
htp.htmlOpen;
htp.headOpen;
htp.title(‘My home page‘);
htp.headClose;
htp.bodyOpen;
htp.print (‘This is the home page of ‘|| user ||‘
generated on ‘ || sysdate || ‘.‘);
htp.bodyClose;
htp.htmlClose;
END;
Pages
1.
Schreiben der PL/SQL Server Page
Standard-Skripttag
Spezielle Skripttags:
- Pages
- Prozeduren
- Parameter
- Deklarationen
- Expression Blocks
- Include
- Kommentare
2.
Kompilieren der PSP-Datei als Stored Procedure
3.
Aufruf der PSP im Browser
Standard-Skripttag
Funktion: Begrenzung von PL/SQL- Anweisungen
Inhalt: beliebige PL/SQL-Statements, z.B.
Prozeduraufrufe
<% PL/SQL code %>
<% PL/SQL code %>
Syntax
Page Direktive
Funktion: Charakterisierung der PSP
Attribute:
–
language: verwendete Skriptsprache (PL/SQL Standard)
–
contentType: Inhaltstyp der Seite; text/html Standard
–
errorPage: PSP-Seite, die auf auftretenden Fehlern aufgerufen wird (Standard: keine Datei)
<% page [language=“PL/SQL“]
[contentType=“content type string“]
[errorPage=“file.psp“] %>
<% page [language=“PL/SQL“]
[contentType=“content type string“]
[errorPage=“file.psp“] %>
Syntax
Spezielle Tags:
Procedure & Parameter Direktive
Funktion: Spezifikation von Prozedur und Parameter (alles IN)
Attribute:
–
procedure: Name des Prozedur
–
parameter: Name des Parameters
–
type: Datentyp des Parameters; Standardwert varchar2 (ohne Länge)
–
default: Standardwert für Parameter
<% plsql procedure=“procedure name“ %>
<% plsql procedure=“procedure name“ %>
Syntax
<% plsql parameter=“parameter name“ %>
[type=“PL/SQL datatype“]
[default=“value“] %>
<% plsql parameter=“parameter name“ %>
[type=“PL/SQL datatype“]
[default=“value“] %>
Declaration Direktive
Funktion: Deklaration von Variablen und Cursor auf der ganzen Seite
Beispiel:
<%! PL/SQL declaration;
[PL/SQL declaration;] ... %>
<%! PL/SQL declaration;
[PL/SQL declaration;] ... %>
Syntax
<%! cursor prod_cur is select * from products
where price between minprice and´maxprice vc_name varchar2(200):=‘Peter‘; %>
<%! cursor prod_cur is select * from products
where price between minprice and´maxprice vc_name varchar2(200):=‘Peter‘; %>
Spezielle Tags:
Expression Block / Print Direktive
Funktion: Ausgabe eines beliebigen PL/SQL-Ausdrucks (String, Zahl, Ergebnis eines Funktionsaufrufs)
Beispiel:
<%= PL/SQL expression %>
<%= PL/SQL expression %>
Syntax
<%= ‘The employee name is ‘|| emp_rec.ename %>
oder
The employee name is <%= emp_rec.ename %>
<%= ‘The employee name is ‘|| emp_rec.ename %>
oder
The employee name is <%= emp_rec.ename %>
Include Direktive
Funktion: Einbinden des Quelltexts anderer Dateien in die Seite
Beispiel:
<%@ include file =“path name“ %>
<%@ include file =“path name“ %>
Syntax
<%= include file=“header.inc“ %>
<%= include file=“header.inc“ %>
Anmerkungen:
-
Datei darf HTML- und PSP-Skriptelemente enthalten
-
Einbindung nur einmal zur Übersetzungszeit (mögliche
Alternative: Einbindung durch Prozeduraufruf)
Spezielle Tags:
Kommentare
Funktion: erscheint nicht in der generierten Prozedur bzw.
in den daraus erstellten HTML-Seiten
<%-- Kommentar --%>
<%-- Kommentar --%>
Syntax
<%!-- Kommentar --%>
<%!-- Kommentar --%>
Syntax
Funktion: Kommentare, die in der HTML-Ausgabe erscheinen (normale HTML-Syntax)
-- einzeiliger Kommentar
/* mehrzeiliger Kommentar */
-- einzeiliger Kommentar
/* mehrzeiliger Kommentar */
Syntax
Funktion: Kommentare innerhalb eines PL/SQL-Blocks
Page
loadpsp [-replace] - user username/password[@connect_string]
[include_file_name ...] [<page1> <page2> ... ]
loadpsp [-replace] - user username/password[@connect_string]
[include_file_name ...] [<page1> <page2> ... ]
Syntax
Beispiel
loadpsp -replace - user name/passw@imnlehre timestamp.inc display_cust.psp
loadpsp -replace - user name/passw@imnlehre timestamp.inc display_cust.psp
Attribute:
-
replace: überschreibt Prozedur gleichen Namens
-
username/password@connect_string: Login-Information
-
include-file_name: Dateien, die mittels include eingebunden werden
-
page1 ...: Name der PSP-Dateien, die kompiliert werden sollen
Beispiel einer Generierung
Verarbeitung des Aufrufs
Parameterverarbeitung GET-Methode
Beispiel:
http://goliath.imn.htwk-leipzig.de:8080/WebDB/
cust_order_items?ord_id=100&cust_id=100
http://goliath.imn.htwk-leipzig.de:8080/WebDB/
cust_order_items?ord_id=100&cust_id=100
URL bei Submit:
...
<form method=“GET“ action=“cust_order_items“>
<input type=“hidden“ name=“cust_id“ value=“<%=cust_id %“>
<input type=“text“ name=“ord_id“ size=“10“ value=“<%=order_id %“>
<input_type=“submit“ value = “Order Details“>
</form>
...
...
<form method=“GET“ action=“cust_order_items“>
<input type=“hidden“ name=“cust_id“ value=“<%=cust_id %“>
<input type=“text“ name=“ord_id“ size=“10“ value=“<%=order_id %“>
<input_type=“submit“ value = “Order Details“>
</form>
...
POST-Methode
Beispiel:
http://goliath.imn.htwk-leipzig.de:8080/WebDB/
cust_order_items
http://goliath.imn.htwk-leipzig.de:8080/WebDB/
cust_order_items
URL bei Submit:
...
<form method=“POST“ action=“cust_order_items“>
<input type=“hidden“ name=“cust_id“ value=“<%=cust_id %“>
<input type=“text“ name=“ord_id“ size=“10“ value=“<%=order_id %“>
<input_type=“submit“ value = “Order Details“>
</form>
...
...
<form method=“POST“ action=“cust_order_items“>
<input type=“hidden“ name=“cust_id“ value=“<%=cust_id %“>
<input type=“text“ name=“ord_id“ size=“10“ value=“<%=order_id %“>
<input_type=“submit“ value = “Order Details“>
</form>
...
Hinweise zur Verwendung von PSP
Trennung von Anwendungs- und Präsentationslogik
–
Berechnungen in eigenständiger Prozedur
Einbinden zusätzlicher Dateien
–
Procedure Invocation = direkter Prozeduraufruf
(bessere Berücksichtigung von Änderungen)
Seitenköpfen und -füßen
<%@ plsql procedure="page_header" %>
<!-- header: links to customer help page and search button -->
<CENTER>
<A HREF="/support/help.html">Customer Help</A>
<FORM ACTION="/product/search_prod"><INPUT NAME="item">
<INPUT TYPE=SUBMIT></FORM>
<HR>
<!-- end of header -->
<%@ plsql procedure="page_header" %>
<!-- header: links to customer help page and search button -->
<CENTER>
<A HREF="/support/help.html">Customer Help</A>
<FORM ACTION="/product/search_prod"><INPUT NAME="item">
<INPUT TYPE=SUBMIT></FORM>
<HR>
<!-- end of header -->
<%@ plsql procedure="page_footer" %>
<!-- footer: company contact info -->
<HR>
<CENTER>
WebStore Inc. <BR>
123 Main Street <BR>
San Francisco, CA 94021 <BR>
(415) 123-4567 <BR>
<A HREF="mailto:sales@webstore.
<!-- end of footer -->
<%@ plsql procedure="page_footer" %>
<!-- footer: company contact info -->
<HR>
<CENTER>
WebStore Inc. <BR>
123 Main Street <BR>
San Francisco, CA 94021 <BR>
(415) 123-4567 <BR>
<A HREF="mailto:sales@webstore.
<!-- end of footer -->
<HTML>
<TITLE>Page Title</TITLE>
<BODY>
<% page_header;%>
... page body
<% page_footer;%>
</BODY>
</HTML>
<HTML>
<TITLE>Page Title</TITLE>
<BODY>
<% page_header;%>
... page body
<% page_footer;%>
</BODY>
</HTML>
Aufruf der Prozeduren
Fehlerbehandlung - Beispiel
create or replace procedure Show_Details
( Prod_ID in Number, Name out varchar2, Price out Number ) as
Prod_Name varchar2(30);
Prod_Price Number;
begin
Select Name, Price
Into Prod_name, Prod_Price From Products
Where ID = Prod_id;
...
Name := Prod_Name;
Price := Prod_Price;
end;
von Errorpages
erwartete vs. unerwartete Fehler
erwarteter Fehler: NO_DATA_FOUND
unerwarteter Fehler: 2 Produkte mit der gleichen ID
Verwendung von ErrorPage in Page-Direktive zur Behandlung unerwarteter Fehler
Nachteil: keine Parameterübergabe möglich (z.B. Fehlerzeitpunkt, Eingabeparameter)
EXCEPTION WHEN OTHERS THEN htp.init;
error; END; -- error: Name der Fehlerseite
Benutzerdefinierte
Ausnahmebehandlung (Exceptions)
<%@ page errorPage="Error_Page.psp" %> -- Angabe der Fehlerseite ...
l_exception EXCEPTION; -- Deklaration der Ausnahme l_exception ...
IF (TO_DATE(arrival_date,'YYYY-MM-DD') <= SYSDATE) THEN
RAISE l_exception; -- Datum liegt vor dem aktuellem Datum END IF;
EXCEPTION
WHEN l_exception THEN -- Test, ob es der vom Benutzer ausgelöste Fehler ist RAISE; -- Weiterleitung des Fehlers an übergeordnete Fehler-
END; -- behandlung in Error_Page ...
<% IF (SQLERRM = 'User-Defined Exception') THEN %>
<% l_error_message := 'Date values should be greater than Current Date'; %>
<%= l_error_message %> -- Ausgabe der Fehlermeldung
<% ELSE %>
<%= SQLERRM %> -- wenn anderer Fehler, Ausgabe der Fehlermeldung
<% END IF; %>
<%@ plsql procedure “show errorPage="Error_Page.psp" %>
<%@ plsql parameter=“p_ID“ type=“number“ default=“0“%>
<%@ plsql parameter=“p_Text“ type=“varchar2“ default=“‘‘“%>
<SELECT NAME = “p_ID“ size=“1“>
<% for item in
(select ID, Name from Products order by Name) loop %>
<option value=“<%=item.ID %>“ ><%=item.Name %></option>
<% end loop; %>
</SELECT>
<SELECT NAME = “p_ID“ size=“1“>
<% for item in
(select ID, Name from Products order by Name) loop %>
<option value=“<%=item.ID %>“ ><%=item.Name %></option>
<% end loop; %>
</SELECT>
SELECT-Box wird durch Abfrage auf Tabelle Products mit Werten gefüllt, Zuordnung zum Parameter p_ID
2. Eingabeparameter: p_Text als Input-Feld in HTML-Formular
<form method=“post“ action=“show_detail“>
<p>Eingabe: <input type=text size=50 maxlength=50 name=“p_Name“>
<SELECT NAME=“p_ID“ size=“1“>
...
</SELECT>
<input type=“submit“ value=“Abschicken“>
<form method=“post“ action=“show_detail“>
<p>Eingabe: <input type=text size=50 maxlength=50 name=“p_Name“>
<SELECT NAME=“p_ID“ size=“1“>
...
</SELECT>
<input type=“submit“ value=“Abschicken“>
Benutzeridentifikation
<form method=“POST“ action=“Startseite“>
<p><b>Kundennummer eingeben:</b>
<INPUT TYPE=“text“ name=“cust_id“ size=“5“>
<input type=“submit“ value=“Login“></p>
</form>
<form method=“POST“ action=“Startseite“>
<p><b>Kundennummer eingeben:</b>
<INPUT TYPE=“text“ name=“cust_id“ size=“5“>
<input type=“submit“ value=“Login“></p>
</form>
Beispiel: Anmeldung mit Kunden-Nr
PSP der Startseite-Prozedur und alle nachfolgenden Prozeduren: Parameter für Kunden-Nr.
<%@ plsql parameter=“cust_id“ type=“number“ %>
<%@ plsql parameter=“cust_id“ type=“number“ %>
Speicherung der Kunden-Nr. in verstecktem Feld, ermöglicht Weitergabe bei Abschicken des Formulars (nicht günstig bei komplexeren Anwendungen!)
<input type=“hidden“ name=“cust_id“ value=<%= cust_id %“ >
<input type=“hidden“ name=“cust_id“ value=<%= cust_id %“ >
keine Einschränkung gegenüber normalen HTML- Seiten
clientseitige Skriptsprache
–
Test von Benutzereingaben vor Abschicken in die Datenbank
Beispiel:
–
Prüfe bei Absenden des Formulars (onSubmit) durch Aufruf einer Javascript-Funktion (chkFormular), die True oder False zurückliefert
–
if TRUE Aufruf der PSP-Prozedur insertCheck
–
vergleiche Quellcode-Beispiel
Anzeige von Master-Detail- Beziehungen (Beispiel)
<%@ plsql procedure=“main“ %>
<html>
<head>
<title>Master/Detail-Text</title>
</head>
<frameset rows=“40%,60%“>
<frame src=“show_Master“ name=“Master“>
<frame src=“show_Detail“ name=“Detail“>
</frameset>
</html>
<%@ plsql procedure=“main“ %>
<html>
<head>
<title>Master/Detail-Text</title>
</head>
<frameset rows=“40%,60%“>
<frame src=“show_Master“ name=“Master“>
<frame src=“show_Detail“ name=“Detail“>
</frameset>
</html>
Darstellung einer Master-Detail-Beziehung in Frames Anzeige der Master-Datensätze: show_Master
Anzeige der Detail-Datensätze: show_Detail
PSP des Master-Frames
<%@ page language="PL/SQL" %>
<%@ plsql procedure="show_Master" %>
<html>
<head><title>Master-Datasets</title></head>
<body>
<form action="show_detail" target="Detail">
<SELECT NAME="p_Cust_ID" size="1">
<% for item in (select * from Customer order by Cust_name) loop %>
<option value="<%= item.Cust_ID %>" ><%=item.Cust_Name
%></option>
<% end loop; %>
</select>
<input type="submit" value="Bestellungen anzeigen">
</form>
</body>
</html>
<title> Detaildatensätze </title>
</head>
<body>
<form>
<table border="1" >
<tr>
<th align="center">Artikelname</td>
<th align="center">Preis</td>
<th align="center">Anzahl</td>
<th align="center">Bestellnummer</td>
<th align="center">Bestellstatus</td>
</tr>
<% for item in (SELECT Order_ID, Order_Number, Order_Sign, Stat_ID, Stat_Desc, Prod_Name, Prod_Price
FROM CustOrders, Status, Products
WHERE ORDER_CUST_ID=p_Cust_ID AND Stat_ID (+)=Order_Status AND
Order_Prod_ID=Prod_ID ORDER BY Prod_Name ) loop
-- (+): Outer Join, um auch Bestellungen auszuwählen, die keinen Status haben%>
<tr>
<td align="left"><%= item.Prod_Name %></td>
<td align="left"><%= item.Prod_Price %></td>
<td align="left"><%= item.Order_Number %></td>
<td align="left"><%= item.Order_Sign %></td>
<td align="left"><%= item.Stat_Desc %></td>
</tr>
<% end loop; %>
</table>
</form>