【问题标题】:Foreign Keys In MySQL DatabaseMySQL 数据库中的外键
【发布时间】:2013-07-16 11:05:50
【问题描述】:

我正在为学校目的构建一个简单的基于 Web 的应用程序,它应该使某些用户能够购买他们从下拉菜单中选择的某些产品。每当用户点击购买他们从下拉菜单中选择的产品时,该产品就会存储到已购买项目表中,同时会从另一个名为 products 的表中删除。据我所知,为了能够做到这一点,我需要有 3 个表:用户、产品、购买,在购买表中我应该有 2 列外键,对于购买者来说是 #1,对于购买者来说是 #2购买的产品。我以为我解决了这个问题,但我的 glassfish 服务器不断向我抛出以下错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
无法添加或更新子行:外键约束失败
(`webprodaja`.`kupljeno`,约束`kupljeno_ibfk_1`外键(`id`)参考users(`id`))

好的,这里是有问题的表和外键:

表“用户”:

id | name
1  | Ivan
2  | Beka
3  | Ogi

表“proizvodi”(英语产品):

id | name
1  | kafa
2  | jafa
3  | ratluk

表“kupljeno”(英语购买):

id | name | proizvod
2  | Beka | 3
3  | Ogi  | 2

表 'kupljeno' 也有 2 个外键:

一个放在“id”列上并引用表“users”及其列“id”的;

另一个放在“proizvod”列上并引用表“proizvodi”及其列“id”;

所以我要做的是删除买家选择的任何产品,并在“proizvod”列中删除其名称,因此将相同的产品放入“kupljeno”列。但是,我能够进行购买并将详细信息存储到“kupljeno”列中,但由于某种原因,我不能再这样做了,更不用说在“proizvod”列中删除正在购买的产品了。

另外,这里是完整的 index.jsp 代码:

<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@page import="java.sql.DriverManager"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
        <body>


    <%


        Class.forName("com.mysql.jdbc.Driver").newInstance();
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/webprodaja","root","");
        Statement st = conn.createStatement();
       // if(request.getParameter("add")!=null){

            ResultSet rs = st.executeQuery("select * from users");
            %>
            <form action="index.jsp" method="post">  
            <select name="user">

                <%
                while(rs.next())
                   {
                    String name=rs.getString(2);
                    String id = rs.getString(1);
                %>

                <option  value="<%=name%>" ><%=name%></option>

                <%
                   }
                %>

            </select> 

                <%

                ResultSet rs1 = st.executeQuery("select * from proizvodi");

                %>

                <select name="proizvod">

                <%
                while(rs1.next())
                   {
                    String name1=rs1.getString(2);
                    String id1 = rs1.getString(1);
                %>

                <option value="<%=id1%>" ><%=name1%></option>

                <%
                   }
                %>

                </select> 
                <input type="submit" name="add" value="buy"/>
             </form>   


                <%

                if(request.getParameter("add")!=null)
                {
                    String user = request.getParameter("user");
                    String proizvod = request.getParameter("proizvod"); 
                    st.execute("insert into kupljeno(id, name, proizvod) values (null, '"+user+"', "+proizvod+")");

                }

                %>                                  


        <%-- <form action="index.jsp" method="post">
           <input type="submit" name="add" value="buy">

       </form> --%>    


    </body>
</html> 

【问题讨论】:

  • 从 products 表中删除产品的原因是什么?
  • 我想将表“proizvodi”中购买的产品放入表“kupljeno”中,然后删除购买的产品,使其看起来像是已购买且不再可用。如何复制产品的 ID 并将其存储在“kupljeno”表的引用列中,然后删除“proizvodi”表中的该值?
  • 那么,当一个用户购买产品时,是否不再可供其他用户购买?因为这就是效果。
  • 是的,这正是我想要实现的目标。
  • 为什么不在产品表中做库存栏,然后当单位有0个库存时它不能购买,当有1个库存时它可以购买。然后,当一个人被购买时,库存会因购买的库存数量而减少。

标签: mysql foreign-keys jsp-tags


【解决方案1】:

您确实需要在 kupljeno 表中提供该外键列的值(而不是 users_id,而是在 kupljeno 表中奇怪地命名。我们通常在每个表上添加一个主键,而这个表没有好像有。

insert into kupljeno(id, name, proizvod) values (null, '"+user+"', "+proizvod+")"
                     ^^                          ^^^^

我怀疑你在kupljeno 表中声明了带有AUTO_INCREMENT 属性的id 列,就好像它是表的主键,而不是另一个表的外键。

我怀疑的原因是,因为您正在插入一个 NULL 值,但试图插入的行有一个值。这要么是因为列上的 AUTO_INCREMENT 属性而被分配的,要么是(在这种情况下不太可能)它是由触发器分配的。

(实际识别问题的方法是实际表定义,可以使用SHOW CREATE TABLE 语句轻松获得。)

我认为您真正想要的是将表的 PRIMARY KEY 与引用 users 表的 FOREIGN KEY 分开,如下所示:

id          - primary key
user_id     - foreign key references user(id)
user_name   - (redundant, copied from user.name)
product_id  - foreign key to product(id)

【讨论】:

  • 'kupljeno.id' 列中的洗牌 id 值存储用户/产品表中的任何 id,它不需要有主键,这个表的目的是显示谁买了什么,而不是按升序排列。我想要做的是摆脱“proizvodi”表中的值,并将这些相同的值放入“kupljeno”表中,具体取决于用户购买了哪种产品。这应该很容易,但由于我正忙于处理这些问题,我需要一个关于如何解决这个问题的想法。我被告知要使用外键解决方案,有人吗?
  • @Ivan Ćeličanin:您将 NULL 值分配给插入语句中的 id 列。因此,这应该是表中的 NULL。但是一个 NULL 值不会抛出你得到的异常。但是,如果尝试插入具有在 users.id 列中未找到的 id 值的行将引发该异常。至于如何调试,请找出引发异常的语句的确切 SQL 文本。我在您发布的代码中看到的唯一可能引发异常的语句是 INSERT。
【解决方案2】:

你说,

同时从另一个名为 products 的表中删除

你也说过,

表 'kupljeno'[purchase] 也有 2 个外键: 一个放在“id”列上并引用表“users”及其列“id”; 另一个放在 'proizvod'[product] 列上并引用表 'proizvodi'[product] 及其列 'id';

当一个表的行对另一个表的行有 fk 约束时,在删除第一个表的行之前,不能删除第二个表的行。你应该阅读this关于外键约束的文章。

为什么要这样做?这是糟糕的设计。不要从产品表中删除。

改为使用您的代码来控制它,以防止用户在需要时购买同一产品两次。不要强迫 MySQL 做它不应该做的事情;让你的代码做它应该做的!

【讨论】:

  • 如前所述,这是为我的学校项目提供的明确指导方针。从“proizvodi”表中取出物品并将其放入“kupljeno”表中,这样看起来就好像购买完成了。我需要处理代码,以便它删除某些行并将它们存储到另一列中。我如何做到这一点?
  • 将购买表中的外键删除到产品表中,然后您应该可以插入购买表并从产品表中删除
  • 好的,我部分解决了问题,GlassFish 不再抛出错误,数据被存储到绑定的“kupljeno”表中。我现在仍然想做的是从“proizvodi”中删除项目并将它们放入“kupljeno”表中。
  • 这可能是对作业的误解吗?从产品表中“获取”产品可能意味着使用其 ID 进行插入,而不是从表中删除整行?我认为,最明显的编码方式是在产品的选择中添加一个 where 子句,指定它们不应该出现在购买表中。 SELECT * FROM proizvodi WHERE NOT EXISTS(SELECT * FROM kupljeno WHERE kupljeno.proizvod = proizvodi.id)sqlfiddle.com/#!2/71177d/1如果您认为这不是解决方案,您能否给出更准确的问题措辞?
猜你喜欢
  • 1970-01-01
  • 2018-11-08
  • 2021-03-05
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多