数据库课程计划——订餐系统(PowerBuilder+SQL Sever)

打印 上一主题 下一主题

主题 965|帖子 965|积分 2897

一、选题先容
本系统要求门生对订餐系统进行计划,包罗用户组设置(如餐厅管理员、顾客),订单管理(如增删改查)等功能,在此基础上对数据库进行计划,要求:符合数据库计划标准,减少冗余度

二、需求分析
(思维导图与系统功能图略,可根据以下文字自行绘制)
系统重要包罗以下功能:
1. 用户管理:通过用户类型(餐厅管理员或顾客)实现差异权限的设置;用户可以登录系统,使用用户名和密码进行身份验证。
2. 餐厅管理:餐厅管理员可以创建与修改餐厅,提供餐厅名称和地点。
3. 菜单管理:餐厅管理员可以为餐厅添加、修改或删除菜单项,包罗菜名、代价和形貌。
4. 订单管理:用户可以欣赏餐厅的菜单,并输入相应菜品信息下订单;餐厅管理员可以查看餐厅的订单。
5. 订单详情:订单详情将记录每个订单中的菜品信息,包罗菜单ID和数目。

三、数据库计划
(一)E-R图(略,可根据以下文字自行绘制)
餐厅和用户之间的关系是多对多关系,一个餐厅可以有多个用户,一个用户可以选择多个餐厅。
用户和订单之间的关系为一对多关系,一个用户可以创建多个订单,而每个订单只属于一个用户。
订单和订单详情之间的关系是一对多关系,一个订单可以有多个订单详情,每个订单详情只属于一个订单。
菜单与订单详情之间的关系是多对多关系,一个订单详情可以对应一个或多个菜单项,而一个菜单项可以出现在多个订单详情中:一个订单大概包罗多个菜品,每个菜品对应一个订单详情,而一个菜品可以在多个订单中出现。
餐厅与菜单之间的关系是一对多关系,一个餐厅可以有多个菜单,但每个菜单只属于一个餐厅。
(二)关系模子:
用户(用户ID,用户名,密码,用户类型)
餐厅(餐厅ID,餐厅名称,餐厅地点,餐厅管理员ID
菜单(菜单ID餐厅ID,菜名,代价,形貌)
订单(订单ID用户ID,订单日期,总价,状态)
订单详情(订单详情ID订单ID菜单ID,数目)
(三)表计划:

计划了五张表,分别是用户表,餐厅表,菜单表,订单表与订单详情表。

用户表(UUser)中包罗了用户ID(UserID),用户名(Username),密码(Password),用户类型(UserType):餐厅管理员或顾客,此中用户ID为主键。

用户表(UUser

列名

数据类型

是否答应为空

形貌

UserID

int

false

用户ID

Username

varchar(50)

true

用户名

Password

varchar(50)

true

密码

UserType

varchar(20)

true

用户类型


餐厅表(Restaurant)中包罗了餐厅ID(RestaurantID),餐厅名称(RestaurantName),餐厅地点(RestaurantAddress),餐厅管理员ID(AdminID),此中餐厅管理员ID为外键,关联用户表中的用户ID。

餐厅表(Restaurant

列名

数据类型

是否答应为空

形貌

RestaurantID

int

false

餐厅ID

Restaurantname

varchar(50)

true

餐厅名称

RestaurantAddress

varchar(100)

true

餐厅地点

AdminID

int

true

餐厅管理员ID


菜单表(Menu)中包罗了菜单ID(MenuID),餐厅ID(RestaurantID),菜名(DishName),代价(Price),形貌(Description),此中菜单ID为主键,餐厅ID为外键,关联餐厅表中的ID。

菜单表(Menu

列名

数据类型

是否答应为空

形貌

MenuID

int

false

菜单ID

RestaurantID

int

true

餐厅ID

DishName

varchar(50)

true

菜名

Price

decimal(8,2)

true

代价

Description

varchar(200)

true

形貌


订单表(OOrder)中包罗了订单ID(OrderID),用户ID(UserID),订单日期(OrderDate),总价(TotalPrice),地点(Address),此中订单ID为主键,用户ID为外键,关联用户表中的用户ID。

订单表(OOrder

列名

数据类型

是否答应为空

形貌

OrderID

int

false

订单ID

UserID

int

true

用户ID

OrderDate

date

true

日期

TotalPrice

decimal(10,2)

true

总价

Address

varchar(20)

true

地点


订单详情表(OrderDetail)中包罗了订单详情ID(DetailID),订单ID(OrderID),菜单ID(MenuID),数目(Quantity),此中订单详情ID为主键,订单ID为外键,关联订单表中的订单ID,菜单ID为外键,关联菜单表中的菜单ID。

订单详情表(OrderDetail

列名

数据类型

是否答应为空

形貌

DetailID

int

false

订单详情ID

OrderID

int

true

订单ID

MenuID

int

true

菜单ID

Quantity

int

true

数目


(四)视图计划:

计划一个名为RestaurantMenuOrderView的视图,将餐厅表、菜单表毗连在一起,提供餐厅名称、菜单号、菜名、代价的信息。使用这个视图可以方便地查看餐厅的菜单信息。

  1. CREATE VIEW RestaurantMenuOrderView AS
  2. SELECT R.RestaurantName, M.MenuID, M.DishName, M.Price
  3. FROM Restaurant R
  4. JOIN Menu M ON R.RestaurantID = M.RestaurantID;
复制代码

 RestaurantMenuOrderView视图

还计划了一个名为OrderDetailView的视图,用来显示订单详情与订单的联合,该视图为顾客计划,提供了直观的订单详情。

  1. CREATE VIEW OrderDetailView AS
  2. SELECT
  3.     OD.detailid,OD.menuid,OD.quantity,O.orderid,O.userid,O.orderdate,O.address
  4. FROM
  5.     OrderDetail OD
  6. JOIN
  7.     OOrder O ON OD.orderid = O.orderid;
复制代码

 OrderDetailView视图

(五)存储过程计划:
计划一个名为GetMenuByRestaurantName的带参数的存储过程,当输入餐厅名称时返回对应的菜单信息。
  1. CREATE PROCEDURE GetMenuByRestaurantName
  2.     @Restaurantname VARCHAR(100)
  3. AS
  4. BEGIN
  5.     SELECT M.MenuID, M.DishName, M.Price, M.Description
  6.     FROM Menu AS M
  7.     INNER JOIN Restaurant AS R ON M.RestaurantID=R.RestaurantID
  8.     WHERE R.Restaurantname = @Restaurantname;
  9. END;
复制代码

GetMenuByRestaurantName存储过程调用

(六)触发器计划:
计划一个名为UpdateTotalPriceOnOrderDetailInsert的触发器,根据订单详情表中的新增记录来更新订单表中的总价。通过内毗连将订单表与新增的订单详情表关联起来,然后使用子查询计算订单详情的总价。子查询中使用 SUM函数计算每个菜单的总价。最后,将计算得出的新总价更新到订单表中。
  1. CREATE TRIGGER UpdateTotalPriceOnOrderDetailInsert
  2. ON OrderDetail
  3. AFTER INSERT,DELETE
  4. AS
  5. BEGIN
  6.     -- Update the TotalPrice in the Order table
  7.     UPDATE OOrder
  8.     SET TotalPrice = (SELECT SUM(D.Price * OD.Quantity)
  9.                      FROM OrderDetail OD
  10.                      INNER JOIN Menu D ON OD.MenuID = D.MenuID
  11.                      WHERE OD.OrderID = OOrder.OrderID)
  12.     FROM OOrder
  13.     INNER JOIN inserted ON OOrder.OrderID = inserted.OrderID;
  14. END;
复制代码

实行以上语句,在订单详情表中对OrderID为1的订单增长了新菜品,再次查询订单表可以发现总价由原来的27.07更新为59.27。

增长语句前


增长语句后

还计划了一个触发器名为ADD_ORDER_DATE,实现增长订单时同步更新当前系统日期。

  1. CREATE TRIGGER ADD_ORDER_DATE
  2. ON OOrder
  3. AFTER INSERT
  4. AS
  5. BEGIN
  6. UPDATE OOrder
  7. SET OrderDate=GETDATE()
  8. WHERE OrderDate is NULL;
  9. END;
复制代码

实行insert语句


系统日期添加乐成

(七)用户计划:

用户类型分为以下两种:


  • 管理员用户,对餐厅、菜单信息进行增删改查,对餐厅订单与订单详情进行改查,但没有删除权限与增长权限,保证订单的真实性,不会出现商家刷单或恶意删除订单;
  • 普通用户,对餐厅,菜单,订单信息进行查找,在餐厅与菜单表中没有增删改权限,但在订单表中可增长订单,无法修改或删除,也可在订单详情表中增长订单详情,但无法修改与删除,这意味着普通顾客想要修改订单信息必要联系餐厅管理员进行修改。
使用ODBC接口时仅使用数据库默认sa账号进行数据库毗连,若想实现差异用户使用差异的数据库账号,可以设置两个ODBC数据源,分别使用餐厅管理员用户和普通顾客用户进行数据库毗连,分为餐厅管理员客户端与普通顾客客户端。

由于制作两个步伐工作量较大,且计划了用户表,用户表中包罗了用户id,用户名,密码与用户类型,我们计划通过登录界面来识别用户类型,用户类型决定用户进入管理员窗口或顾客窗口,以达到差异用户差异权限的功能,因此只在此写出数据库用户授权的代码,本次课程计划中没有效到。

  1. --创建餐厅管理员用户
  2. CREATE LOGIN Restaurant_admin WITH PASSWORD='88888888';
  3. CREATE USER Restaurant_admin FOR LOGIN Restaurant_admin;
复制代码
  1. --授予all权限,收回订单与订单详情表中的删除权限与增加权限
  2. GRANT all privileges ON Menu TO restaurant_admin;
  3. GRANT all privileges ON OOrder TO restaurant_admin;
  4. REVOKE DELETE ON OOrder FROM restaurant_admin;
  5. REVOKE INSERT ON OrderDetail FROM restaurant_admin;
  6. GRANT all privileges ON OrderDetail TO restaurant_admin;
  7. REVOKE DELETE ON OrderDetail FROM restaurant_admin;
  8. REVOKE INSERT ON OOrder FROM restaurant_admin;
  9. GRANT all privileges ON Restaurant TO restaurant_admin;
复制代码
普通顾客数据库用户创建于授权代码如下:

  1. --创建普通顾客用户
  2. CREATE LOGIN Restaurant_customer WITH PASSWORD='11111111';
  3. CREATE USER Restaurant_customer FOR LOGIN Restaurant_customer;
复制代码
  1. --授予查看菜单表、餐厅表,订单表与订单详情,增加订单与订单详情权限
  2. GRANT SELECT ON Menu TO restaurant_customer;
  3. GRANT SELECT ON OOrder TO restaurant_customer;
  4. GRANT INSERT ON OOrder TO restaurant_customer;
  5. GRANT SELECT ON OrderDetail TO restaurant_customer;
  6. GRANT INSERT ON OOrder TO restaurant_customer;
  7. GRANT SELECT ON Restaurant TO restaurant_customer;
复制代码

四、数据库实现
  1. --创建数据库
  2. CREATE DATABASE RO;
  3. --创建用户表
  4. CREATE TABLE UUser (
  5.   UserID INT PRIMARY KEY,
  6.   Username VARCHAR(50),
  7.   Password VARCHAR(50),
  8.   UserType VARCHAR(20)
  9. );
  10. --创建餐厅表
  11. CREATE TABLE Restaurant (
  12.   RestaurantID INT PRIMARY KEY,
  13.   RestaurantName VARCHAR(50),
  14.   RestaurantAddress VARCHAR(100),
  15.   AdminID INT,
  16.   FOREIGN KEY (AdminID) REFERENCES UUser(UserID)
  17. );
  18. --创建菜单表
  19. CREATE TABLE Menu (
  20.   MenuID INT PRIMARY KEY,
  21.   RestaurantID INT,
  22.   DishName VARCHAR(50),
  23.   Price DECIMAL(8, 2),
  24.   Description VARCHAR(200),
  25.   FOREIGN KEY (RestaurantID) REFERENCES Restaurant(RestaurantID)
  26. );
  27. --创建订单表
  28. CREATE TABLE OOrder (
  29.   OrderID INT PRIMARY KEY,
  30.   UserID INT,
  31.   OrderDate DATE,
  32.   TotalPrice DECIMAL(10, 2),
  33.   Address VARCHAR(20),
  34.   FOREIGN KEY (UserID) REFERENCES UUser(UserID)
  35. );
  36. --创建订单详情表
  37. CREATE TABLE OrderDetail (
  38.   DetailID INT PRIMARY KEY,
  39.   OrderID INT,
  40.   MenuID INT,
  41.   Quantity INT,
  42.   FOREIGN KEY (OrderID) REFERENCES OOrder(OrderID),
  43.   FOREIGN KEY (MenuID) REFERENCES Menu(MenuID)
  44. );
  45. --插入用户表数据
  46. INSERT INTO UUser (UserID, Username, Password, UserType)
  47. VALUES (1, 'admin', 'admin123', '餐厅管理员');
  48. INSERT INTO UUser (UserID, Username, Password, UserType)
  49. VALUES (2, 'john_doe', 'password123', '顾客');
  50. INSERT INTO UUser (UserID, Username, Password, UserType)
  51. VALUES (3, 'jane_smith', '123456', '顾客');
  52. INSERT INTO UUser (UserID, Username, Password, UserType)
  53. VALUES (4, 'michelle_ang', '667798', '顾客');
  54. INSERT INTO UUser (UserID, Username, Password, UserType)
  55. VALUES (5, 'adam_louis', 'adam145534', '顾客');
  56. --插入餐厅表数据
  57. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  58. VALUES (1, '餐厅A', '地址A', 1);
  59. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  60. VALUES (2, '餐厅B', '地址B', 1);
  61. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  62. VALUES (3, '餐厅C', '地址C', 1);
  63. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  64. VALUES (4, '餐厅D', '地址D', 1);
  65. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  66. VALUES (5, '餐厅E', '地址E', 1);
  67. INSERT INTO Restaurant (RestaurantID, RestaurantName, RestaurantAddress, AdminID)
  68. VALUES (6, '餐厅F', '地址F', 1);
  69. --插入菜单表数据
  70. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  71. VALUES (1, 1, '菜品1', 10.99, '这是菜品1的描述');
  72. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  73. VALUES (2, 1, '菜品2', 15.99, '这是菜品2的描述');
  74. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  75. VALUES (3, 2, '菜品3', 12.99, '这是菜品3的描述');
  76. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  77. VALUES (4, 2, '菜品4', 13.10, '这是菜品4的描述');
  78. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  79. VALUES (5, 3, '菜品5', 24.28, '这是菜品5的描述');
  80. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  81. VALUES (6, 3, '菜品6', 12.06, '这是菜品6的描述');
  82. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  83. VALUES (7, 4, '菜品7', 31.49, '这是菜品7的描述');
  84. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  85. VALUES (8, 4, '菜品8', 6.89, '这是菜品8的描述');
  86. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  87. VALUES (9, 5, '菜品9', 23.55, '这是菜品9的描述');
  88. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  89. VALUES (10, 5, '菜品10', 36.62, '这是菜品10的描述');
  90. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  91. VALUES (11, 6, '菜品11', 32.20, '这是菜品11的描述');
  92. INSERT INTO Menu (MenuID, RestaurantID, DishName, Price, Description)
  93. VALUES (12, 6, '菜品12', 27.07, '这是菜品12的描述');
  94. --插入订单表数据
  95. INSERT INTO OOrder (OrderID, UserID, OrderDate, TotalPrice, Address)
  96. VALUES (1, 2, '2023-05-20', 27.07, '用户地址');
  97. INSERT INTO OOrder (OrderID, UserID, OrderDate, TotalPrice, Address)
  98. VALUES (2, 3, '2023-05-21', 47.10, '用户地址');
  99. INSERT INTO OOrder (OrderID, UserID, OrderDate, TotalPrice, Address)
  100. VALUES (3, 4, '2023-05-20', 47.97, '用户地址');
  101. INSERT INTO OOrder (OrderID, UserID, OrderDate, TotalPrice, Address)
  102. VALUES (4, 5, '2023-05-17', 6.89, '用户地址');
  103. --插入订单详情表数据
  104. INSERT INTO OrderDetail (DetailID, OrderID, MenuID, Quantity)
  105. VALUES (1, 1, 12, 1);
  106. INSERT INTO OrderDetail (DetailID, OrderID, MenuID, Quantity)
  107. VALUES (2, 2, 9, 2);
  108. INSERT INTO OrderDetail (DetailID, OrderID, MenuID, Quantity)
  109. VALUES (3, 3, 2, 3);
  110. INSERT INTO OrderDetail (DetailID, OrderID, MenuID, Quantity)
  111. VALUES (4, 4, 8, 1);
复制代码
  1. --创建视图CREATE VIEW RestaurantMenuOrderView AS
  2. SELECT R.RestaurantName, M.MenuID, M.DishName, M.Price
  3. FROM Restaurant R
  4. JOIN Menu M ON R.RestaurantID = M.RestaurantID;
复制代码
  1. CREATE VIEW OrderDetailView AS
  2. SELECT
  3.     OD.detailid,OD.menuid,OD.quantity,O.orderid,O.userid,O.orderdate,O.address
  4. FROM
  5.     OrderDetail OD
  6. JOIN
  7.     OOrder O ON OD.orderid = O.orderid;
复制代码
  1. --创建存储过程
  2. CREATE PROCEDURE GetMenuByRestaurantName
  3.     @Restaurantname VARCHAR(100)
  4. AS
  5. BEGIN
  6.     SELECT M.MenuID, M.DishName, M.Price, M.Description
  7.     FROM Menu AS M
  8.        INNER JOIN Restaurant AS R ON M.RestaurantID=R.RestaurantID
  9.     WHERE R.Restaurantname = @Restaurantname;
  10. END;
复制代码
  1. --创建更新总代价触发器CREATE TRIGGER UpdateTotalPriceOnOrderDetailInsert
  2. ON OrderDetail
  3. AFTER INSERT,DELETE
  4. AS
  5. BEGIN
  6.     -- Update the TotalPrice in the Order table
  7.     UPDATE OOrder
  8.     SET TotalPrice = (SELECT SUM(D.Price * OD.Quantity)
  9.                      FROM OrderDetail OD
  10.                      INNER JOIN Menu D ON OD.MenuID = D.MenuID
  11.                      WHERE OD.OrderID = OOrder.OrderID)
  12.     FROM OOrder
  13.     INNER JOIN inserted ON OOrder.OrderID = inserted.OrderID;
  14. END;
复制代码
  1. --创建同步日期触发器CREATE TRIGGER ADD_ORDER_DATE
  2. ON OOrder
  3. AFTER INSERT
  4. AS
  5. BEGIN
  6. UPDATE OOrder
  7. SET OrderDate=GETDATE()
  8. WHERE OrderDate is NULL;
  9. END;
复制代码

五、系统实现
使用SQL Sever创建数据库,PowerBuilder9.0实现窗口,ODBC接口毗连数据库,编程语言使用PB语言。
(一)窗口先容
为实现订餐系统,创建了7个窗口:w_main为登录主界面,w_admin管理员界面与w_customer顾客界面为w_main的子页面,管理员界面中实现了餐厅管理与菜单管理功能,包罗餐厅信息的增删改查,菜单信息的增删改查,w_order订单管理界面为w_admin的子界面,提供订单管理功能,包罗对订单的修改与查找;w_customer_order顾客订单查看界面、w_address增长新订单界面与w_add加菜界面都为w_customer的子界面。


(二)功能实现
(1)用户登录

w_main窗口

通过与用户表中的用户类型对照,管理员登录必要勾选“管理员登录”按钮,否则提示“用户不存在”;普通用户登录若勾选了该按钮,同样也提示“用户不存在”;理所当然地,若输错用户名也将提示“用户不存在”,当用户名与密码与用户类型与用户表中数据同等时,提示登岸乐成。





 代码实现:在登录按钮的clicked事件中编辑代码如下:
  1. string userPwd,userType
  2. GS_USERNAME=trim(sle_1.text) 
  3. userPwd=trim(sle_2.text) 
  4. if cbx_1.checked = true then
  5.        userType="餐厅管理员"
  6. else
  7.        userType="顾客"
  8. end if
  9.       
  10. if GS_USERNAME ="" then          
  11.        messagebox("提示","用户名不能为空")
  12. else
  13.        SELECT Username
  14.        into :GS_USERNAME
  15.        from "UUser"
  16.        where "UUser"."Username"=:GS_USERNAME AND "UUser"."UserType"=:userType;
  17.       
  18.        //SQLCode=100证明没有找到记录,此用户不存在 
  19.        if SQLCA.SQLCode=100 then 
  20.               messagebox("提示","用户不存在")
  21.        else
  22.               //该用户存在查询密码是否正确
  23.              
  24.               SELECT Username
  25.               into :GS_USERNAME
  26.               from "UUser"
  27.               where "UUser"."Username"=:GS_USERNAME and "UUser"."Password"=:userPwd;
  28.                     
  29.               if SQLCA.SQLCode=100 then 
  30.                      messagebox("提示","密码不正确")
  31.               else
  32.                      messagebox("提示","登录成功")
  33.                      if userType="餐厅管理员" then
  34.                             open(w_admin)
  35.                             close(parent)
  36.                      else
  37.                             open(w_customer)
  38.                             close(parent)
  39.                      end if
  40.               end if
  41.        end if
  42. end if
复制代码
值得留意的是,除了这里的userpwd和usertype变量之外,必要在全局中定义一个GS_username变量,将文本框中的值赋给该全局变量,以方便后面判断用户名输入。
在退出按钮的clicked事件中添加关闭窗口代码
  1. close(w_main)
复制代码
(2)顾客点餐

w_customer窗口

顾客点餐窗口展示了所有餐厅与餐厅对应的菜单,此处使用的是RestaurantMenuOrderView视图,在数据窗口中选择对应的数据,并在窗口页面的open事件中写入以下代码以显示。

  1. dw_1.settransobject(sqlca)
  2. dw_1.retrieve()
复制代码
(a)点餐

点击“去点餐”按钮进入下单页面:

在按钮的clicked事件中写入打开w_address窗口的代码打开下单窗口。


w_address窗口


在窗口中输入信息,若用户名与登任命户名不同等则提示“请输入与登岸时相同的登录名”,当用户名同等时提示“下单乐成”。



代码实现:
  1. string uaddress,userid,username,mmenuid,quantity
  2. username=string(sle_1.text)
  3. uaddress=string(sle_2.text)
  4. mmenuid=string(sle_3.text)
  5. quantity=string(sle_4.text)
  6. if username=gs_username then
  7.        select userid into:userid from uuser where username=:username;
  8.        int maxdetailid,maxorderid
  9.        select max(detailid) into:maxdetailid from orderdetail;
  10.        select max(orderid) into:maxorderid from orderdetail;
  11.        int neworderid,newdetailid
  12.        neworderid=maxorderid+1
  13.        newdetailid=maxdetailid+1
  14.        now_orderid=string(neworderid)
  15.        string orderinsert,detailinsert
  16.        orderinsert="insert into [oorder](orderid) values("+string(neworderid)+")"
  17.        detailinsert="insert into [orderdetail](detailid) values("+string(newdetailid)+")"
  18.        execute immediate:orderinsert using sqlca;
  19.        execute immediate:detailinsert using sqlca;
  20.        string orderupdate
  21.        orderupdate="update oorder set userid ='"+userid+"',address='"+uaddress+"' where userid is null and address is null"
  22.        execute immediate:orderupdate using sqlca;
  23.        string detailupdate
  24.        detailupdate="update orderdetail set orderid='"+now_orderid+"',menuid ='"+mmenuid+"',quantity='"+quantity+"' where orderid is null and menuid is null and quantity is null"
  25.        execute immediate:detailupdate using sqlca;
  26.       
  27.        messagebox("提示","下单成功!")
  28.        close(w_address)
  29. else
  30.        messagebox("提示","请输入与登录时相同的用户名!")
  31.       
  32. end if
复制代码
此段代码的重要目的是获取文本框中的文字,将文本框中的文字添加到表中。首先获取当前订单详情表中订单详情号与订单号的最大值,然后在订单表与订单详情表中新插入一个最大值加1的订单详情号与订单号,插入完毕后表格中除了订单号与订单详情号别的都为NULL值,最后将文本框中获取的文本信息update到表中,条件为 xxx is NULL,由于已经写了自动添加日期的触发器,不必要专程输入日期,插入新的订单号时,触发insert事件,自动在表中加入了系统日期。
(b)加菜

点击顾客界面的“去加菜”进入加菜窗口。与“去点餐”按钮中的代码相似,打开w_add窗口。


w_add窗口


输入菜单号与数目,点击立刻加菜按钮弹出加菜乐成窗口。
代码实现:
  1. string mmenuid,quantity
  2. mmenuid=string(sle_3.text)
  3. quantity=string(sle_4.text)
  4. int maxdetailid,maxorderid
  5. select max(detailid) into:maxdetailid from orderdetail;
  6. select max(orderid) into:maxorderid from orderdetail;
  7. int newdetailid
  8. newdetailid=maxdetailid+1
  9. string orderinsert,detailinsert
  10. detailinsert="insert into [orderdetail](detailid) values("+string(newdetailid)+")"
  11. execute immediate:detailinsert using sqlca;
  12. string detailupdate
  13. detailupdate="update orderdetail set orderid='"+string(maxorderid)+"',menuid ='"+mmenuid+"',quantity='"+quantity+"' where orderid is null and menuid is null and quantity is null"
  14. execute immediate:detailupdate using sqlca;     
  15. messagebox("提示","加菜成功!")
  16. close(w_add)
复制代码

此段代码与“去下单”中的代码逻辑雷同,获取当前订单详情表中的订单详情最大值与订单号最大值,然后在订单详情表中新插入一个订单详情号最大值加1的值,实现每按一次该按钮就插入新的行,除了订单详情号与订单号外别的字段都为NULL,然后将文本框中的值更新到表格中,条件为xxx is NULL,值得留意的是,加菜的订单号就为最大值,不加1。
(c)查看订单
在“查看订单”按钮中写入打开w_customer_order窗口的代码,打开窗口。

w_customer_order窗口

上图是初始只有一条信息的状态,经过了一轮下单,一轮加菜,窗口中的信息更新为:

可见订单号都为5号,地点与日期都为下单时的信息,但订单详情号差异,菜单号与数目是加菜时填入的菜单与数目。
数据窗口选择相应的数据,然后在此处在窗口的open事件中写入以下代码:
  1. int uuserid
  2. select userid into:uuserid from uuser where username=:gs_username;
  3. dw_1.settransobject(sqlca)
  4. dw_1.retrieve(uuserid)
复制代码
这里的gs_username是最开始定义的全局变量,存放了登录时输入的用户名的值,通过select语句查找条件为用户表中用户名即是gs_username的用户号,然后通过retrieve(uuserid)只显示该用户号的订单信息。
(3)管理员餐厅管理

w_admin窗口

在该界面中放置了7个按钮,此中“餐厅”与“菜单”按钮点击后可以查看餐厅表与菜单表

                               餐厅表                                                                 菜单表
点击添加可以添加新的一行,可在内里添加文字;点击保存即可保存到表格中;点击删除即可删除这一行,弹出警告框再次确认,点击确定即可删除。

                               添加                                                                         保存
​​​​​​​

                                    删除警告                                                         已删除
代码实现:
在数据窗口中的rowfocuschanged事件中添加代码如下:
  1. dw_1.selectrow(0,false)
  2. dw_1.selectrow(dw_1.getrow(),true)
复制代码
在餐厅按钮的clicked事件中添加代码如下:
  1. dw_1.dataobject='dw_restaurant'
  2. dw_1.SetTransObject(sqlca)
  3. dw_1.Retrieve()
复制代码
菜单按钮同理,只必要更换表格的数据窗口就行。
添加按钮的clicked事件代码如下:
  1. integer i_newrow
  2. i_newrow=dw_1.insertrow(0)
  3. dw_1.scrolltorow(i_newrow)
复制代码
删除按钮的clicked事件代码如下:
  1. int i
  2. i=messagebox("警告","真的要删除吗?",exclamation!,Okcancel!,2)
  3. if i=1 then
  4.                               dw_1.deleterow(0)
  5.                               dw_1.update()
  6.                               dw_1.retrieve()
  7. end if
复制代码
保存按钮的clicked事件代码如下:
  1. dw_1.update()
  2. dw_1.retrieve()
复制代码
订单按钮的clicked事件用于打开w_order窗口,退出按钮则是关闭当前w_admin窗口。
(4)管理员订单管理

w_order窗口

第一个数据窗口中显示订单概况,第二个数据窗口中显示第一个数据窗口中选中行的订单号相干订单详情。
点击排序的两个按钮,可实现按日期降序与按单号升序,点击按日期降序可以看到最顶上为刚刚顾客下的5号订单,第二个数据窗口中出现了两个订单详情,订单号都为5。


点击计算总金额,可以计算当前订单的总金额。


5号订单的总金额


2号订单的总金额

用户下的新订单总金额为空,管理员必要手动输入总金额并保存订单,若订单信息必要修改,可以一并修改后点击“保存”。
代码实现:

首先在窗口的open事件中写入以下代码以显示数据:

  1. dw_1.settransobject(sqlca)
  2. dw_1.retrieve()
复制代码
在第一个数据窗口中的rowfocuschanged事件中写入如下代码:

  1. int i_row
  2. int s_num
  3. i_row=dw_1.getrow()
  4. dw_1.selectrow(0,false)
  5. dw_1.selectrow(i_row,true)
  6. s_num=dw_1.getitemnumber(i_row,"orderid")
  7. oorderid=s_num
  8. dw_2.settransobject(sqlca)
  9. dw_2.retrieve(oorderid)
复制代码
此部分的代码用于获取鼠标选中行上的orderid,然后将值赋给oorderid,使用retrieve(oorderid)实现数据窗口的数据显示。

oorderid也是一个全局变量,存放了鼠标选中行的orderid,以便于计算对应订单总金额。

值得留意的是,第二个数据窗口中的数据必要设置好sql语句,如下图所示,要先定义一个number型变量orderid,然后写入查询条件中,否则无法实现第二个数据窗口的信息跟随鼠标选中的第一个数据窗口的行的特定值改变。



 

排序功能使用了setsort函数,A为升序,D为降序,按日期降序按钮代码如下:
  1. dw_1.setsort("orderdate D")
  2. dw_1.sort()
复制代码
同理,按单号升序代码如下:
  1. dw_1.setsort("orderid A")
  2. dw_1.sort()
复制代码
总金额的计算代码:
  1. string price
  2. SELECT SUM(Menu.Price * OrderDetail.Quantity)
  3. into:price
  4. FROM OrderDetail,Menu
  5. WHERE OrderDetail.MenuID=Menu.MenuID
  6. AND OrderDetail.OrderID=:oorderid;
  7. sle_1.text=price
复制代码

此处用到了前面定义的全局变量oorderid,通过select语句毗连菜单表与订单详情表,找出订单详情表中的菜单id对应的代价,然后计算该代价与订单详情表中数目的乘积,用SUM聚合函数求与oorderid的值相等的订单详情表中的orderid的代价之和,即为总金额。

至此,该订餐系统的功能展示完毕。

订餐系统的流程为:管理员在管理员界面添加餐厅与菜单信息,顾客通过下单页面欣赏菜单并下单,顾客可加菜并查看本身的订单,管理员可在订单管理处按日期降序优先查询到新的订单,新的订单未登记总金额,点击计算总金额后,顾客线下付款,管理员手动登入该订单总金额并保存,订单完成。


作者的话:该订餐系统还有许多地方必要完满,课设时间有限只能做到这个田地了,比如说创建的存储过程没用上,自动更新总价的触发器也没改好,其实这个是因为后面的加菜功能里我写的代码是update,而触发器的条件是insert和delete,我在编加菜功能的时候写insert死活报错,最后才选择使用update语句,这一点可以改一改,管理订单页面两个数据窗口的订单号同步那边有一点难度,必要好好摸索一番,bilibili上有我的演示视频,有大部分的代码讲解,可以去参考看看。数据库课程计划PowerBuilder9.0+SQL Sever_哔哩哔哩_bilibili


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南七星之家

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表