MyBatis-16MyBatis动态SQL之【支持多种数据库】

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS SQL Server,基础系列 2核4GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: MyBatis-16MyBatis动态SQL之【支持多种数据库】

概述


MyBatis-15MyBatis动态SQL之【bind】 bind标签并不能解决更换数据库带来的所有问题。 那么还有没其他的方式来支持不同的数据库呢 ?


答案是 使用if标签以及由MyBatis提供的databaseIdProvider数据库厂商标识配置


MyBatis可以根据不同的数据库厂商执行不同的SQL,这种多厂商的支持是基于映射语句中的databaseId属性。 MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。 如果同时找到了带有databaseId和不带databaseId的相同语句,则不带databaseId的将被舍弃。


配置


1.MyBatis全局配置文件增加


为了支持多厂商数据库,需要在MyBatis全局配置文件中加入databaseIdProvider配置 <databaseIdProvider type="DB_VENDOR"/>


也可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider 并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider


DB_VENDOR会通过DatabaseMetaData#getDatabaseProductName()返回的字符串进行设置, 通常情况下这个字符串比较长而且相同产品的不同版本会返回不同的值,通常会设置属性别名使其变短。

    <!-- 多数据库支持 -->
    <databaseIdProvider type="DB_VENDOR">
        <property  name ="SQL  Server" value="sqlserver"/>
        <property  name ="DB2" value ="db2"/>
        <property  name ="Oracle" value ="oracle"/>
        <property  name ="MySQL" value ="mysql"/>
        <property  name ="PostgreSQL" value ="postgresql"/>
        <property  name ="Derby" value ="derby"/>
        <property  name ="HSQL" value ="hsqldb"/>
        <property  name ="H2" value ="h2"/>
    </databaseIdProvider>


上述列举了常见的数据库产品名称,在有property配置时,databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值,如果没有匹配则置为null .


DB_VENDOR的匹配策略为DatabaseMetaData#getDatabaseProductName()返回的字符串包含property中name部分的值即可匹配。


数据库产品名一般由选择的当前数据库的JDBC驱动所决定,只要找到对应数据库DatabaseMetaData的实现类,一般在getDatabaseProductName()方法中就可以直接找到该值。

任何情况下都可以通过调用DatabaseMetaData#getDatabaseProductName()来获取具体的值


完整的mybatis-config.xml如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入外部属性文件 ,必须放在第一位-->
    <properties resource="db.properties"/>
    <settings>
        <!-- 通过logImpl属性指定使用LOG4J输出日志,mybatis默认使用log4j作为输出日志信息。 -->
        <setting name="logImpl" value="LOG4J" />
        <!-- 通过配置这个属性为true可以自动将下画线方式命名的数据库列映射到java对象驼峰式命名属性中
        <setting name="mapUnderscoreToCamelCase" value="true"/>
         -->
    </settings>
    <!-- typeAliases元素下配置了一个包的别名,通常确定一个类的时候需要使用全限定名,
        比如 com.artisan.mybatis.simple.mapper.model.Country
    -->
    <typeAliases>
        <package name="com.artisan.mybatis.simple.model" />
    </typeAliases>
    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池-->
            <dataSource type="UNPOOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    <!-- 多数据库支持 -->
    <databaseIdProvider  type="DB_VENDOR" >
        <property  name ="SQL  Server" value="sqlserver"/>
        <property  name ="DB2" value ="db2"/>
        <property  name ="Oracle" value ="oracle"/>
        <property  name ="MySQL" value ="mysql"/>
        <property  name ="PostgreSQL" value ="postgresql"/>
        <property  name ="Derby" value ="derby"/>
        <property  name ="HSQL" value ="hsqldb"/>
        <property  name ="H2" value ="h2"/>
    </databaseIdProvider>
    <mappers>
        <!-- 配置具体的mapper -->
        <mapper resource="com/artisan/mybatis/simple/mapper/CountryMapper.xml" />
        <!-- 逐一配置,比较繁琐,容易遗漏,接口方式不推荐
        <mapper resource="com/artisan/mybatis/xml/mapper/UserMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/UserRoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/PrivilegeMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RolePrivilegeMapper.xml"/>
         -->
        <!-- 推荐:通过包的方式配置,mybatis会先查找对应包下的所有的接口 -->
        <package name="com.artisan.mybatis.xml.mapper"/>
    </mappers>
</configuration>


注意databaseIdProvider节点的位置。


2.映射文件中的标签调整包含databaseId属性

除了增加上述配置之外,映射文件也需要调整,关键在于下面几个映射文件的标签中含有的databaseId属性


  • select
  • insert
  • update
  • delete
  • selectKey
  • sql

示例


20180428040311282.png


举个简单的例子,查询当前时间

我们知道 mysql中的语句为

select now() from dual


oracle中为

select sysdate from dual


增加个查询当前时间的接口


结合mybatis全局配置文件中的 mappers-package节点,在com.artisan.mybatis.xml.mapper包中增加接口

MultiDBMapper.java

package com.artisan.mybatis.xml.mapper;
public interface MultiDBMapper {
    String getSysTime();
}

编写映射文件


MultiDBMapper.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
                    "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!-- 当Mapper接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->                    
<mapper namespace="com.artisan.mybatis.xml.mapper.MultiDBMapper">
    <select id="getSysTime"  resultType="String" databaseId="mysql">
        select now() from dual
    </select>
     <select id="getSysTime"   resultType="String" databaseId="oracle">
         select  'oralce-'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss')  from dual 
     </select>
</mapper>   


单元测试

package com.artisan.mybatis.xml.mapper;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.util.Properties;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class MultiDBMapperTest extends BaseMapperTest {
    public String getDatabaseProductName() {
        String productName = null;
        try {
            String dbfile = "db.properties";
            InputStream in = ClassLoader.getSystemResourceAsStream(dbfile);
            Properties p = new Properties();
            p.load(in);
            Class.forName(p.getProperty("jdbc.driver"));
            String url = p.getProperty("jdbc.url");
            String user = p.getProperty("jdbc.username");
            String pass = p.getProperty("jdbc.password");
            Connection con = DriverManager.getConnection(url, user, pass);
            DatabaseMetaData dbmd = con.getMetaData();
            productName = dbmd.getDatabaseProductName();
            System.out.println("数据库名称是:" + productName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return productName;
    }
    @Test
    public void getSysTimeTest() {
        // 获取数据库名称
        getDatabaseProductName();
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        // 获取MultiDBMapper
        MultiDBMapper multiDBMapper = sqlSession.getMapper(MultiDBMapper.class);
        // 调用接口方法
        String sysTime = multiDBMapper.getSysTime();
        System.out.println("当前时间:" + sysTime);
        sqlSession.close();
    }
}


日志

2018-04-27 16:05:57,730  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-27 16:05:57,730  INFO [main] (BaseMapperTest.java:29) - reader close successfully
数据库名称是:MySQL
2018-04-27 16:05:57,819 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: select now() from dual 
2018-04-27 16:05:57,929 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 
2018-04-27 16:05:57,959 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: now()
2018-04-27 16:05:57,959 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 2018-04-27 16:05:57.0
2018-04-27 16:05:57,969 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
当前时间:2018-04-27 16:05:57.0


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


注意事项

我们在上面演示了基于databaseId的基本用法,实际在工作中,大部分的SQL还是相同的,没有必要写成2个。这样会导致大量重复的SQL。


数据库的更换可能只会引起某个SQL语句的部分不同, 可以使用if标签配合默认的上下文中的_databaseId参数去实现。

我们用前几篇博文的例子来演示下

改造前

<select id="selectSysUsersAdvancedWithWhere" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                and user_name like concat('%',#{userName},'%')
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>


改造后

<!-- 多数据库的支持 BEGIN -->
    <select id="selectSysUsersAdvancedMulitDB" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                <if test="_databaseId == 'mysql' ">
                    and user_name like concat('%',#{userName},'%')
                </if>
                <if test="_databaseId == 'oracle' ">
                    and user_name like '%'||#{username}||'%'
                </if>
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>
    <!-- 多数据库的支持 END -->


增加个接口方法,方便区分测试

/**
     * 
     * 
     * @Title: selectSysUsersAdvancedMulitDB
     * 
     * @Description: selectSysUsersAdvancedMulitDB
     * 
     * @param sysUser
     * @return
     * 
     * @return: List<SysUser>
     */
    List<SysUser> selectSysUsersAdvancedMulitDB(SysUser sysUser);


单元测试

@Test
    public void selectSysUsersAdvancedMulitDBTest() {
        logger.info("selectSysUsersAdvancedMulitDBTest");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        List<SysUser> userList = null;
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            logger.info("===========1.当用户只输入用户名时,需要根据用户名模糊查询===========");
            // 模拟前台传参 1.当用户只输入用户名时,需要根据用户名模糊查询
            SysUser sysUser = new SysUser();
            sysUser.setUserName("ad");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有1条数据
            Assert.assertTrue(userList.size() == 1);
            logger.info("userList:" + userList);
            // 为了测试 匹配多条记录的情况,我们将id=1001这条数据的userName 由test 改为artisan
            sysUser.setUserName("i");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin和artisan, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有2条数据
            Assert.assertTrue(userList.size() == 2);
            logger.info("userList:" + userList);
            logger.info("===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========");
            // 模拟前台传参 2.当用户只输入邮箱使,根据邮箱进行完全匹配
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvanced(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            sysUser.setUserEmail("1admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info("===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========");
            // 模拟组合查询条件,存在记录的情况
            sysUser.setUserName("i");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertEquals("admin@artisan.com", sysUser.getUserEmail());
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            logger.info("===========4.当用户同时输入无法匹配的用户名和密码===========");
            // 模拟组合查询条件,不存在记录的情况
            sysUser.setUserName("x");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvancedMulitDB(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info(userList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-27 16:22:51,822  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-27 16:22:51,826  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-27 16:22:51,827  INFO [main] (UserMapperTest.java:934) - selectSysUsersAdvancedMulitDBTest
2018-04-27 16:22:51,857  INFO [main] (UserMapperTest.java:943) - ===========1.当用户只输入用户名时,需要根据用户名模糊查询===========
2018-04-27 16:22:51,987 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') 
2018-04-27 16:22:52,086 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: ad(String)
2018-04-27 16:22:52,157 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,157 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,167 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,167  INFO [main] (UserMapperTest.java:953) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') 
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String)
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,177 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,177 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 2
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:964) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018], SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:966) - ===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE 1=1 and user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), admin@artisan.com(String)
2018-04-27 16:22:52,187 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,187 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,187  INFO [main] (UserMapperTest.java:972) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,187 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), 1admin@artisan.com(String)
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-27 16:22:52,197  INFO [main] (UserMapperTest.java:978) - ===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,197 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), admin@artisan.com(String)
2018-04-27 16:22:52,197 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-27 16:22:52,207 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:987) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:989) - ===========4.当用户同时输入无法匹配的用户名和密码===========
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like concat('%',?,'%') and user_email = ? 
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: x(String), admin@artisan.com(String)
2018-04-27 16:22:52,207 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-27 16:22:52,207  INFO [main] (UserMapperTest.java:995) - []
2018-04-27 16:22:52,217  INFO [main] (UserMapperTest.java:1001) - sqlSession close successfully 


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
SQL 机器学习/深度学习 人工智能
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
本文系统性地阐述了自然语言转SQL(NL2SQL) 技术如何让非技术背景的业务分析师实现数据自助查询,从而提升数据驱动决策的效率与准确性。
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
|
3月前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
376 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
|
2月前
|
SQL 存储 监控
SQL日志优化策略:提升数据库日志记录效率
通过以上方法结合起来运行调整方案, 可以显著地提升SQL环境下面向各种搜索引擎服务平台所需要满足标准条件下之数据库登记作业流程综合表现; 同时还能确保系统稳健运行并满越用户体验预期目标.
194 6
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
3月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
4月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
291 18
|
3月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
294 8
|
4月前
|
SQL 人工智能 Java
用 LangChain4j+Ollama 打造 Text-to-SQL AI Agent,数据库想问就问
本文介绍了如何利用AI技术简化SQL查询操作,让不懂技术的用户也能轻松从数据库中获取信息。通过本地部署PostgreSQL数据库和Ollama模型,结合Java代码,实现将自然语言问题自动转换为SQL查询,并将结果以易懂的方式呈现。整个流程简单直观,适合初学者动手实践,同时也展示了AI在数据查询中的潜力与局限。
451 8
|
4月前
|
SQL 人工智能 Linux
SQL Server 2025 RC0 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC0 发布 - 从本地到云端的 AI 就绪企业数据库
270 5
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。