H2用户自定义函数被多次调用

Posted

技术标签:

【中文标题】H2用户自定义函数被多次调用【英文标题】:H2 user-defined function is called many times 【发布时间】:2014-10-09 16:36:36 【问题描述】:

我使用的是 h2 v1.3.176。 我有执行 RECURSIVE 查询的用户定义函数。

public static ResultSet getChildCategories(Connection connection, long categoryId) throws SQLException 
    String sql = 
            "WITH RECURSIVE r(CATEGORY_ID, PARENT_ID) AS (\n" +
            "    SELECT   CATEGORY_ID\n" +
            "            ,PARENT_ID\n" +
            "    FROM     CATEGORY\n" +
            "    WHERE    CATEGORY_ID = " + categoryId + "\n" +
            "    UNION ALL\n" +
            "    SELECT   CATEGORY.CATEGORY_ID\n" +
            "            ,CATEGORY.PARENT_ID\n" +
            "    FROM     CATEGORY, r\n" +
            "    WHERE    CATEGORY.PARENT_ID = r.CATEGORY_ID\n" +
            ")\n" +
            "SELECT CATEGORY_ID FROM r";
    ResultSet resultSet = connection.createStatement().executeQuery(sql);
    SimpleResultSet rs = new SimpleResultSet();
    rs.addColumn("CATEGORY_ID", Types.INTEGER, 12, 0);
    try 
        while(resultSet.next()) 
            rs.addRow(resultSet.getLong(1));
        
     finally 
        resultSet.close();
    
    return rs;

我已经按照 SQL 注册了这个函数。

create alias GET_CHILD_CATEGORIES for "com.myapp.db.function.Functions.getChildCategories";

我的问题是当我执行以下查询时,getChildCategories 函数会被多次调用。

SELECT DISTINCT  B.BOOK_ID
                ,B.SERIES_ID
                ,B.TITLE
                ,B.ISBN
                ,B.VOLUME
                ,(
                    SELECT  MAX(SAME_SERIES.VOLUME)
                    FROM    BOOK SAME_SERIES
                    WHERE   SAME_SERIES.SERIES_ID = B.SERIES_ID
                    AND     SAME_SERIES.VOLUME IS NOT NULL
                ) AS VOLUME_COUNT
                ,B.PAGE_COUNT
                ,B.FILE_PATH
                ,B.SORTABLE_FILE_NAME
                ,B.SIZE
                ,B.HASH
                ,B.COVER_IMAGE_TYPE
                ,B.COVER_PAGE_NO
                ,B.COVER_LARGE_IMAGE_URL
                ,B.COVER_SMALL_IMAGE_URL
                ,B.COVER_CROP_COORD
                ,B.IS_ENCRYPT
                ,B.PUBLISHER_ID
                ,B.PUBLISHED_DATE
                ,B.CREATION_TIME
                ,B.LAST_MODIFIED_TIME
                ,B.NOTE
                ,B.IS_ISBN_SEARCH
                ,S.CATEGORY_ID
                ,S.TITLE
                ,BA.AUTHOR_ID
                ,BT.TAG_ID
FROM             BOOK AS B
INNER JOIN       SERIES AS S ON S.SERIES_ID = B.SERIES_ID
LEFT OUTER JOIN  BOOK_TAG AS BT ON BT.BOOK_ID = B.BOOK_ID
LEFT OUTER JOIN  BOOK_AUTHOR AS BA ON BA.BOOK_ID = B.BOOK_ID
WHERE 
(
    S.CATEGORY_ID IN (SELECT CATEGORY_ID FROM GET_CHILD_CATEGORIES(106))
    And 
    S.IS_COMPLETION = 1
)
ORDER BY  BA.AUTHOR_ID

为什么会多次调用这个函数?

【问题讨论】:

【参考方案1】:

摘自H2 documentation

返回结果集的函数可以像表格一样使用。 但是,在这种情况下,该函数至少被调用两次:第一次 在解析语句以收集列名时(使用 在编译时未知的参数设置为 null)。进而, 在执行语句以获取数据时(如果 这是一个连接)。如果调用函数只是为了获取列 列表,传递给函数的连接的 URL 是 jdbc:列列表:连接。否则,连接的 URL 是 jdbc:default:connection.

第一次调用仅用于检索结果集列类型。然后你必须检查连接 url 是否为“jdbc:columnlist:connection”。如果为 true,您必须返回一个带有列列表的空结果集。

连接url测试是:

connection.getMetaData().getURL().equals("jdbc:columnlist:connection");

【讨论】:

非常感谢!!就像你说的那样。我能够提高查询性能。 好东西!仍然适用于版本 1.4.200。

以上是关于H2用户自定义函数被多次调用的主要内容,如果未能解决你的问题,请参考以下文章

优化 MySQL 查询,避免对用户自定义函数的不必要调用

自定义函数中的 WINAPI BeginPaint 和 TextOut 多次调用

java 如何让用户自定义函数呢?

C语言中,同一个函数可以被定义多次吗?

如何在shader中使用自定义函数

H2 用户使用“WITHIN GROUP”定义的 ListAgg 函数