# 4.6 多数据库支持

bind标签并不能解决更换数据库带来的所有问题，那么还可以通过什么方式支持不同的数据库呢？这需要用到**if 标签**以及由MyBatis提供的**databaseIdProvider**数据库厂商标识配置。

MyBatis可以根据不同的数据库厂商执行不同的语句，这种多厂商的支持是**基于映射语句中的databaseId属性**的。

* MyBatis会加载**不带databaseId属性**和**带有匹配当前数据库databaseId属性**的所有**语句**。
* 如果同时找到带有databaseId和不带databaseId的相同语句，则后者会被舍弃。

为支持多厂商特性，只要像下面这样加入databaseIdProvider配置即可。

```java
private static final Properties DB_VENDOR = new Properties();
static {
  DB_VENDOR.put("SQL Server", "sqlserver");
  DB_VENDOR.put("DB2", "db2");
  DB_VENDOR.put("Oracle", "oracle");
  DB_VENDOR.put("MySQL", "mysql");
  DB_VENDOR.put("PostgreSQL", "postgresql");
  DB_VENDOR.put("Derby", "derby");
  DB_VENDOR.put("HSQL", "hsqldb");
  DB_VENDOR.put("H2", "h2");
}

VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
databaseIdProvider.setProperties(DB_VENDOR);
sqlSessionFactoryBean.setDatabaseIdProvider(databaseIdProvider);
```

上面列举了常见的数据库产品名称，在存在匹配项时，databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值，如果没有匹配的属性则会被设置为null。在这个例子中，如果getDatabaseProductName()返回Microsoft SQL Server，databaseId将被设置为sqlserver。

> DB\_VENDOR的匹配策略为部分匹配（使用String.contains方法进行判断），所以虽然SQL Server的产品全名一般为Microsoft SQL Server，但这里只要设置为SQL Server就可以匹配。

<mark style="color:blue;">**数据库产品名一般由所选择的当前数据库的JDBC驱动所决定**</mark>（DatabaseMetaData从connection对象中获取），只要找到对应数据库DatabaseMetaData接口的实现类，一般在getDatabaseProductName()方法中就可以直接找到该值。任何情况下都可以通过调用DatabaseMetaData#getDatabaseProductName()方法获取具体的值。

除了增加上面的配置外，映射文件也是要变化的，关键在于以下几个映射文件的标签中含有的**databaseId**属性：select、insert、delete、update、selectKey、sql。

```xml
<select id="selectByName" resultMap="BaseResultMap" databaseId="mysql">
  select 
  	ID, `NAME`, CODE
  from country
  where 
  	`NAME` like = concat('%', #{name}, '%')
</select>

<select id="selectByName" resultMap="BaseResultMap" databaseId="oracle">
  select 
  	ID, `NAME`, CODE
  from country
  where 
  	`NAME` like = '%'||#{name}||'%'
</select>
```

当基于不同数据库运行时，MyBatis会根据配置找到合适的SQL去执行。

数据库的更换可能只会引起某个SQL语句的部分不同，所以也没有必要使用上面的写法，而**可以使用 if 标签配合默认的上下文中的\_databaseId参数**这种写法去实现。这样可以避免大量重复的SQL出现，方便修改。

```xml
<select id="selectByName" resultMap="BaseResultMap" databaseId="oracle">
  select 
  	ID, `NAME`, CODE
  from country
  <where>
    <if test="_databaseId == 'mysql'">
      `NAME` like = concat('%', #{name}, '%')
    </if>
    <if test="_databaseId == 'oracle'">
      `NAME` like = '%'||#{name}||'%'
    </if>
  </where>
</select>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bohans.gitbook.io/ji-chu/mybatis/ji-chu-zhi-shi/4.-dong-tai-sql/4.6-duo-shu-ju-ku-zhi-chi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
