我在使用内部和左侧连接的MySQL查询时遇到问题。问题是,如果允许NULL的字段中主表中的外键为空,则查询不会读取主表中的所有字段。
我的任务是用MySQL组织录音列表,其中一些是现场录音,而另一些是录音室录音。出于这个问题的目的,我正在简化表结构如下:
table name: recordings
fields:
recording_id INT AUTO-INCREMENT
recording_name VARCHAR NOT NULL
artist_id INT NOT NULL FOREIGN KEY
event_id INT NULL FOREIGN KEY
table name: artists
fields:
artist_id INT AUTO-INCREMENT
artist_name VARCHAR NOT NULL
table name: events
fields:
event_id INT AUTO-INCREMENT
event VARCHAR NOT NULL
venue_id INT NOT NULL FOREIGN KEY
table_name: venues
fields:
venue_id INT AUTO-INCREMENT
venue_name VARCHAR NOT NULL
address VARCHAR NOT NULL
如果现场录制,我想要提供录制完成事件的详细信息,如果是录音室录音,我将事件字段留空。换句话说,在recordings
表中event_id
是一个可选字段,但始终需要artist_id
。
要编辑recordings
表中的现有记录,我有一个包含三个字段的表单(再次简化):
<form>
<input name="recording_name" type="text" value="<?php $recording_name ?>" />
<select name="artist_id">
<option>Select option</option>
<option <?php $selected ?> value="1">Artist 1</option>
etc.
</select>
<select name="event_id">
<option>Select option</option>
<option <?php $selected ?> value="1">Venue 1</option>
etc.
</select>
</form>
我使用$selected
变量显示与表单下拉列表中从数据库中提取的现有值相对应的选项,如下所示:
$selected = ($existing_value == $option_id ? 'selected="selected" : '');
现在,为了获取表单的现有值,我有以下SQL查询:
$recording_sql =
'SELECT * FROM recordings
INNER JOIN artists ON recordings.artist_id = artists.artist_id
LEFT JOIN events ON recordings.event_id = events.event_id
LEFT JOIN venues ON events.venue_id = venues.venue_id'
然后,填充两个下拉列表:
$artist_sql =
'SELECT * FROM artists'
$event_sql =
SELECT * FROM events
INNER JOIN venues ON events.venue_id = venues.venue_id
我的PHP代码看起来像这样:
function buildForm($result){
$data = $result->fetch_array($MYSQLI_ASSOC))
$form = '<input name="recording_id" type="hidden" value="'.$data['recording_id'].'" />';
$form .='<input name="recording_name" type="text" value="'.$data['recording_name'].'" />';
$form .= buildSelectBox('artists', $data['artist_id']);
$form .= buildSelectBox('events', $data['event_id']);
return $form;
}
function buildSelectBox($table, $existing_id = NULL){
//run SQL to pull data from relevant table (i.e. $artist_sql, or $event_sql which includes join to 'venues')
//Loop through $mysqli_result to build each option
while(etc....){
$selected = ($existing_id == $option_id ? 'selected="selected" : '');
$options_list .= '<option'.$selected.'value="'.$id.'">'.$artist_name.'</option>';
}
return $options_list;
}
如果两个外键都有值,这可以正常工作。但是,当event_id
中的recordings
字段为空时,它也不会读取其他外键。它读取文本字段recording_name
,虽然很好。换句话说,我为$recordings_sql
获得的结果集仅包含recording_name
字段的值,而两个外键都返回空白,即使其中一个不为空。我已经尝试了不同组合中的所有连接排列(左,内,右),但它们都没有给出所需的结果。
我很难过!提前感谢您的帮助!
答案 0 :(得分:0)
我昨天大部分时间都在尝试使用我的应用程序的简化版本重现问题,最终我做到了。事实证明,第一个外键(在我的简化示例中为artist_id)在另一个表中重复,该表以一系列以第二个外键开头的连接(在我的简化示例中为event_id)开始。所以,我的猜测是,如果'event_id'为null,'artist_id'会被空值覆盖,因为如果'event_id'为空,查询将为'event_id'之后的所有内容返回空值。因此,问题不在于LEFT JOIN如何工作,而是在子表中重复第一个外键,该子表依赖于允许为空的第二个外键。我显然需要重新审视我的表结构...
非常感谢所有的建议!