在匹配子句中使用视图和 table 值函数作为节点或边 table

Use views and table valued functions as node or edge tables in match clauses

我喜欢用Table Valued functions in MATCH clauses in the same way as is possible with Node tables。有办法实现吗?

需要 table 值函数

使用 table 值函数或视图作为 Node tables 可以有多种用例。例如我的如下。
我有 Node table 包含 NVarChar(max) 字段,我想在这些字段中搜索文字文本。我只需要相等搜索,不需要 full text searching, so I opted for using a index on the hash value of the text field. As suggested by Remus Rusanu in his answer to SQL server - worth indexing large string keys? and https://www.brentozar.com/archive/2013/05/indexing-wide-keys-in-sql-server/. A table valued function handles using the CHECKSUM index; see .

示例数据定义

CREATE TABLE [Tags](
    [tag] NVarChar(max),
    [tagHash] AS CHECKSUM([Tag]) PERSISTED NOT NULL
) as Node;

CREATE TABLE [Sites](
    [endPoint] NVarChar(max),
    [endPointHash] AS CHECKSUM([endPoint]) PERSISTED NOT NULL
) as Node;

CREATE TABLE [Links] as Edge;

CREATE INDEX [IX_TagsByName] ON [Tags]([tagHash]);

GO

CREATE FUNCTION [TagsByName](
    @tag NVarChar(max))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT
    $node_id AS [NodeId],
    [tag],
    [tagHash]
FROM [dbo].[Tags]
WHERE [tagHash] = CHECKSUM(@tag) AND
    [tag] = @tag;

[TagsByName] returns $node_id 根据 。但是,真正的 Node tables 包含两个我不知道如何导出的内部列。

所需查询

我想查询类似这样的数据库:

SELECT *
FROM [TagsByName]('important') as t,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t]-([l])->[s])

但是,这会导致错误1:

Msg 13901, Level 16, State 2, Line ...
Identifier 't' in a MATCH clause is not a node table or an alias for a node table.

有办法吗?


PS。有一些解决方法,但它们看起来不像 MATCH-query 那样优雅;特别是考虑到我的实际查询涉及匹配更多关系和更多字符串相等性测试。我将 post 这些解决方法作为答案,并希望有人提出更好的主意。

1 这给出了 Difference between View and table in sql; which only occurs in 的视图和 tables 之间非常具体的区别,并且仅在使用 [=69= 时] 图.

解决方法

通过 JOIN clauses or FROM with <table_or_view_name> and WHERE clauses. In queries that match on more relations, the latter has the advantage that can MATCH on FROM <table_or_view_name> but not on FROM <table_source> JOIN <table_source> 恢复到传统的关系连接。

SELECT *
FROM [TagsByName]('important') as t
    [Sites] as s,
    [Links] as l
WHERE t.NodeId = l.$from_id AND
    l.$to_id = s.$node_id;

解决方法

Node table 两次添加到 from 子句:一次作为 table 一次作为 table 值函数并通过 $node_id 加入它们在 where 子句中:

SELECT *
FROM [TagsByName]('important') as t1,
    [Tags] as t2,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t2]-([l])->[s]) AND
    t1.[NodeId] = t2.$node_id

这会影响性能吗?

解决方法

不使用 table 值函数,但在 WHERE 子句中包含其表达式:

SELECT *
FROM [Tags] as t,
    [Sites] as s,
    [Links] as l
WHERE MATCH ([t]-([l])->[s]) AND
    [t].[tagHash] = CHECKSUM('important') AND
    [t].[tag] = 'important'

缺点:这个容易出错;例如忘记加入 CHECKSUM