• 第2章丨IRIS SQL —— 隐式联接(箭头语法)


    写在前面

    InterSystems SQL 提供了一个特殊的 –> 运算符作为从相关表获取值的简写,而在某些常见情况下,无需指定显式 JOIN 的复杂性。此箭头语法可以代替显式连接语法使用,也可以与显式连接语法结合使用。箭头语法执行左外连接

    箭头语法可用于引用类的属性或父表的关系属性。其他类型的关系和外键不支持箭头语法。不能在 ON 子句中使用箭头语法 (–>)。

    1. 属性引用

    可以使用 –> 运算符作为从“引用的表”中获取值的简写。

    1.1 定义两个类

    例如,假设您定义了两个类:

    Company:

    Class Sample.Company Extends %Persistent [DdlAllowed]
    {
    /// The Company name
    Property Name As %String;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    员工:

    Class Sample.Employee Extends %Persistent [DdlAllowed]
    {
    /// The Employee name
    Property Name As %String;
    
    /// The Company this Employee works for
    Property Company As Company;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.2 使用 –> 运算符

    Employee 类包含一个属性,该属性是对 Company 对象的引用。在基于对象的应用程序中,可以使用点语法遵循此参考。例如,要查找员工为其工作的公司的名称,请执行以下操作:

     Set name = employee.Company.Name
    
    • 1

    您可以使用使用 OUTER JOIN 联接来联接 EmployeeCompany 表的 SQL 语句执行相同的任务:

    SELECT Sample.Employee.Name, Sample.Company.Name AS CompName
    FROM Sample.Employee LEFT OUTER JOIN Sample.Company
    ON Sample.Employee.Company = Sample.Company.ID
    
    • 1
    • 2
    • 3

    使用 –> 运算符,可以更简洁地执行相同的 OUTER JOIN 操作:

    SELECT Name, Company->Name AS CompName
    FROM Sample.Employee
    
    • 1
    • 2

    1.2 在where子句中使用 –> 运算符

    您可以随时使用 –> 运算符,只要您在表中有引用列;也就是说,其值是引用表的 ID 的列(实质上是外键的特殊情况)。在本例中,Sample.Employee 的“公司”字段包含 Sample.Company 表中的记录 ID。可以在查询中使用列表达式的任何位置使用 –> 运算符。例如,在 WHERE 子句中:

    SELECT Name,Company AS CompID,Company->Name AS CompName
    FROM Sample.Employee
    WHERE Company->Name %STARTSWITH 'G'
    
    • 1
    • 2
    • 3

    这等效于:

    SELECT E.Name,E.Company AS CompID,C.Name AS CompName
    FROM Sample.Employee AS E, Sample.Company AS C
    WHERE E.Company = C.ID AND C.Name %STARTSWITH 'G'
    
    • 1
    • 2
    • 3

    1.3 在 GROUP BY 子句中使用 –> 运算符

    可以在 GROUP BY 子句中使用 –> 运算符:

    SELECT Name,Company->Name AS CompName
    FROM Sample.Employee
    GROUP BY Company->Name
    
    • 1
    • 2
    • 3

    1.4 在 ORDER BY 子句中使用 –> 运算符

    您可以在 ORDER BY 子句中使用 –> 运算符:

    SELECT Name,Company->Name AS CompName
    FROM Sample.Employee
    ORDER BY Company->Name
    
    • 1
    • 2
    • 3

    1.5 使用–> 运算符列的列别名

    或者引用 ORDER BY 子句中 –> 运算符列的列别名:

    SELECT Name,Company->Name AS CompName
    FROM Sample.Employee
    ORDER BY CompName
    
    • 1
    • 2
    • 3

    1.6 复合箭头语法

    支持复合箭头语法,如下面的示例所示。在此示例中,Cinema.Review 表包括 Film 字段,该字段包含 Cinema.Film 表的行 ID。Cinema.Film 表包括“类别”字段,该字段包含 Cinema.Category 表的行 ID。因此,Film->Category->CategoryName访问这三个表,以返回具有ReviewScore的每部电影的CategoryName:

    SELECT ReviewScore,Film,Film->Title,Film->Category,Film->Category->CategoryName
    FROM Cinema.Review
    ORDER BY ReviewScore
    
    • 1
    • 2
    • 3

    2. 子表引用

    可以使用 –> 运算符来引用子表。例如,如果 LineItemsOrders 表的子表,则可以指定:

    SELECT LineItems->amount
    FROM Orders
    
    • 1
    • 2

    请注意,订单中没有名为 LineItems 的属性。LineItems 是包含金额字段的子表的名称。此查询在结果集中为每个 Order 行生成多行。它等效于:

    SELECT L.amount
    FROM Orders O LEFT JOIN LineItems L ON O.id=L.custorder
    
    • 1
    • 2

    2.1 表名有包名

    
    SELECT Patient->PA_ScreenNo,*
    		FROM DHCDoc_GCPBC_Base.Plan
    
    • 1
    • 2
    • 3

    3. 箭头语法权限

    使用箭头语法时,您必须对两个表中引用的数据具有 SELECT 权限。您必须对引用的列具有表级 SELECT 特权或列级 SELECT 特权。使用列级权限时,您需要对被引用表的 ID 以及被引用的列具有 SELECT 权限。

    以下示例演示了所需的列级特权:

    SELECT Name,Company->Name AS CompanyName
    FROM Sample.Employee
    GROUP BY Company->Name
    ORDER BY Company->Name
    
    • 1
    • 2
    • 3
    • 4

    在上面的示例中,您必须具有列级 SELECT 特权才能 Sample.Employee.NameSample.Company.NameSample.Company.ID

      SET tStatement = ##class(%SQL.Statement).%New()
      SET privchk1="%CHECKPRIV SELECT (Name,ID) ON Sample.Company"
      SET privchk2="%CHECKPRIV SELECT (Name) ON Sample.Employee"
    CompanyPrivTest
      SET qStatus = tStatement.%Prepare(privchk1)
        IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
      SET rset = tStatement.%Execute()
      IF rset.%SQLCODE=0 {WRITE !,"have Company privileges",! }
      ELSE {  WRITE !,"No privilege: SQLCODE=",rset.%SQLCODE,! }
    EmployeePrivTest
      SET qStatus = tStatement.%Prepare(privchk2)
        IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
      SET rset = tStatement.%Execute()
      IF rset.%SQLCODE=0 {WRITE !,"have Employee privilege",! }
      ELSE {  WRITE !,"No privilege: SQLCODE=",rset.%SQLCODE }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    Flutter异常上报及性能监控实现
    链表OJ练习(2)
    面试突击24:为什么wait和notify必须放在synchronized中?
    JVM内存模型介绍
    mysql GRANT创建用户授权
    定义一个交通工具(Vehicle)的类
    基于ansible批量实现部署数据库主从复制
    KVM虚拟化介绍和安装使用方法
    Caputo 分数阶一维问题基于 L1 逼近的快速差分方法(附Matlab代码)
    动态规划步骤
  • 原文地址:https://blog.csdn.net/DUQGQG/article/details/126174595