用于CREATE TABLE的MySQL Errno 150(不正确的外键)

时间:2016-11-15 17:12:13

标签: java mysql jdbc

我承认这里已多次询问过这个问题,并且我已经查看过很多答案。

我知道errno150指的是一个外键不正确的表,我已经看到了之前的回答here。我检查了那里的每一个条件,无法解决这个问题。不知道我是否遗漏了一些明显的东西。

这是使用MySQL的java实现,我是一个switch语句,它创建了两个表(目前),如下所示:

//Creates the table with the name given to the function and adds all fields & keys
            switch(tableName){
            case "Address":
                stmt.executeUpdate("CREATE TABLE Address(houseNo INT(4) NOT NULL, "
                        + "firstLine VARCHAR(30) NOT NULL, "
                        + "secondLine VARCHAR(30), "
                        + "city VARCHAR(25) NOT NULL, "
                        + "county VARCHAR(25) NOT NULL, "
                        + "postCode VARCHAR(7) NOT NULL, "
                        + "PRIMARY KEY (houseNo, postCode))");
                break;
            case "Patient":
                stmt.executeUpdate("CREATE TABLE Patient(patientID INT(8) NOT NULL PRIMARY KEY AUTO_INCREMENT, "
                        + "title VARCHAR (10) NOT NULL, "
                        + "forename VARCHAR(15) NOT NULL, "
                        + "surname VARCHAR(25) NOT NULL, "
                        + "dob DATE NOT NULL, "
                        + "phoneNo CHAR(11) NOT NULL, "
                        + "houseNo INT(4) NOT NULL, "
                        + "postCode VARCHAR(7) NOT NULL, "
                        + "amountOwed DECIMAL(5,2) NOT NULL, "
                        + "FOREIGN KEY (houseNo) REFERENCES Address (houseNo), "
                        + "FOREIGN KEY (postCode) REFERENCES Address (postCode))");
                break;
            }

地址创建正常(没有外键),患者给出errno150。相同的引擎,相同的字符集,相同的数据类型(甚至复制粘贴为100%确定),新创建的(空)表,都是非临时的。

感谢。

P.S。我无法使用SHOW ENGINE INNODB STATUS,因为我没有足够高的权限级别。

完整的错误消息:

java.sql.SQLException: Can't create table 'team.Patient' (errno: 150)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
    at com.mysql.jdbc.StatementImpl.executeUpdateInternal(StatementImpl.java:1540)
    at com.mysql.jdbc.StatementImpl.executeLargeUpdate(StatementImpl.java:2595)
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1468)
    at uk.team.App.makeTable(App.java:146)
    at uk.team.App.setupEnviro(App.java:80)
    at uk.team.App.access$1(App.java:45)
    at uk.team.App$1.run(App.java:33)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

3 个答案:

答案 0 :(得分:2)

如果要创建与父表的相同行中的两个列匹配的外键约束,则需要为两列指定单个FOREIGN KEY(而不是每列有两个单独的FK约束。)

这适用于MySQL 5.6.13:

stmt.executeUpdate("CREATE TABLE Address(houseNo INT(4) NOT NULL, "
        + "firstLine VARCHAR(30) NOT NULL, "
        + "secondLine VARCHAR(30), "
        + "city VARCHAR(25) NOT NULL, "
        + "county VARCHAR(25) NOT NULL, "
        + "postCode VARCHAR(7) NOT NULL, "
        + "PRIMARY KEY (houseNo, postCode))");
stmt.executeUpdate("CREATE TABLE Patient(patientID INT(8) NOT NULL PRIMARY KEY AUTO_INCREMENT, "
        + "title VARCHAR (10) NOT NULL, "
        + "forename VARCHAR(15) NOT NULL, "
        + "surname VARCHAR(25) NOT NULL, "
        + "dob DATE NOT NULL, "
        + "phoneNo CHAR(11) NOT NULL, "
        + "houseNo INT(4) NOT NULL, "
        + "postCode VARCHAR(7) NOT NULL, "
        + "amountOwed DECIMAL(5,2) NOT NULL, "
        + "FOREIGN KEY (houseNo, postCode) REFERENCES Address (houseNo, postCode))");

答案 1 :(得分:1)

由于Address表没有问题,这与Patient表的引用更相关,我假设team是数据库名称:

  1. 从我在这里看到的,引用的列应该被编入索引。您已经同时创建了一个索引(houseNopostCode),为什么不尝试单独为它们创建索引并查看它是否适合您?

  2. 虽然您已经提到过使用相同的引擎,字符集等,但为什么不在上面的查询中明确提及它们并运行它们。你可以在查询中添加ENGINE = InnoDB吗?

  3. 请告诉我如果它不适合您。

    Can't create table (errno: 150) InnoDB adding foreign key constraints

答案 2 :(得分:0)

所以答案(更多是妥协)我来了:

    function min_get_events ( $echo = true ) {
     $events = new WP_query(array(
    'post_type' => 'events',
    'posts_per_page' => -1,
    'order' => 'ASC',
    'orderby' => 'meta_value',
    'meta_key' => 'min_event-start',
    'meta_query' => array(
        'key'     => 'min_event-start',
        'value'   => date('Y-m-d'),
        'compare' => '>',
    )
));

$i = 0;
$n = 1;

if ( $events->have_posts() ) :
    while ( $events->have_posts() ):
        global $post;
        $events->the_post();

        $open_date = get_post_meta($post->ID, 'min_event-start', true);
        $close_date = get_post_meta($post->ID, 'min_event-end', true);
        $start = strtotime($open_date);
        $end = strtotime($close_date);
        if ($start==$end || $start > $end) {
            $date_string = date('F j, Y', $start);
        }
        else {
            $date_string = date('F j, Y', $start) .' – '. date('F j, Y', $end);
        }
        //$description = get_post_meta($post->ID, 'event-description', true);
        $location = get_post_meta($post->ID, 'min_event-location', true);
        $url = get_post_meta($post->ID, 'min_event-url', true);
        //$registration_url = get_post_meta($post->ID, 'event-registration-url', true);
        $cta_text = get_post_meta($post->ID, 'min_event-cta-text', true);
        $cta = !empty($cta_text) ? $cta_text : 'Register Now';

        $i++;
        if ( $i == 1 ) {
            ?>
            <div class="row">
            <?php
        }
        ?>
        <div class="event col-sm-4">
            <a href="<?= $url ?>">
                <?php the_post_thumbnail('thumb-events'); ?>
            </a>
            <h1><?= htmlentities($post->post_title) ?></h1>
            <div >
                <div><?= $date_string; ?></div>
                <div><?= htmlentities($location) ?></div>
                <div><a href="<?=$url;?>" class="register-now"><?= $cta; ?></a></div>
            </div>
            <!-- <p><?= $description ?></p> -->
            <!-- <p><a href="<?=$url;?>" class="register-now"><?= $cta; ?></a></p> -->
        </div> <!-- .event -->
        <?php


        if ( $i == 3  || ($events->current_post +1) == $events->post_count) {
            ?>
            </div> <!-- <?php echo $i; ?> .row <?php echo $n; ?> -->
            <?php
            $i = 0;
            $n++;
        }

    endwhile;
endif;

ob_start();
?>

<?php
$return = ob_get_contents();
ob_end_clean();
wp_reset_postdata();
if ( $echo ) {
    echo $return;
} else {
    return $return;
}
 }

在“地址”中创建一个附加字段,其中包含作为主键的ID以及“患者”中唯一引用的外键。它并不理想,但功能齐全。