最近的工作遇到了连接查询,特在此记录,以免日后遗忘。以前学SQL连接查询的时候,通篇都是理论和数学公式,既抽象又不便于理解,因此我在这里以一个最通俗易懂的例子来说明。首先在SqlServer中建立两个表:TProvince和TCity,前者记录省,后者记录市,其数据如下所示:
Id ProvinceName
1 浙江省
2 江苏省
3 安徽省
4 广东省
Id CityName ProvinceId
1 杭州市 1
2 湖州市 1
3 嘉兴市 1
4 南京市 2
5 苏州市 2
6 无锡市 2
7 合肥市 3
8 芜湖市 3
9 六安市 3
10 济南市 5
// 内连接
private void button1_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] inner join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
从结果可以看出,内连接就是获取两张表能够对应上的数据,因此广东省和济南市这两条记录不会显示。
// 左连接
private void button2_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] left join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
从结果可以看出,左连接确保了市的名称全部显示,但广东省由于没有对应的市,因此没有显示。因此左连接其实就是确保左边数据表记录的完整,右边则不去管它。
// 右连接
private void button3_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] right join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
从结果可以看出,右连接确保了右边数据表的完整,而左边则不去管它。
// 全连接
private void button4_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] full join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
// 交叉连接
private void button5_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] cross join [TProvince]";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
从结果可以看出,交叉连接就不管对应不对应了,它只是左边数据与右边数据的逐一匹配,也就是笛卡尔积。全部代码如下所示:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
// 连接字符串
private static string ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
// 构造函数
public Form1()
{
InitializeComponent();
}
// 内连接
private void button1_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] inner join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
// 左连接
private void button2_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] left join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
// 右连接
private void button3_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] right join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
// 全连接
private void button4_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] full join [TProvince] on [TCity].ProvinceId=[TProvince].Id";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
// 交叉连接
private void button5_Click(object sender, EventArgs e)
{
string commandText = "select * from [TCity] cross join [TProvince]";
using (SqlDataAdapter adapter = new SqlDataAdapter(commandText, ConnectionString))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
}
}