选择查询中的从属列

时间:2013-03-27 11:39:37

标签: sql sql-server select

我有一张表员工

+-------+---------+-------------+
| Empid |  Name   |   Mailid    |
+-------+---------+-------------+
|   001 | abc def | abc@xyz.com |
|   002 | hij klm | hij@xyz.com |
|   003 | nop qrs | nop@xyz.com |
+-------+---------+-------------+

我可以查询它:

select 
    Empid, 
    Left(Name,3),
    'hardcoded string',
    Mailid,
    Replace(Mailid,'@xyz.com','') 
from Employee;

如何显示上述查询是否直接或间接引用了员工中的特定列?例如:

col1 Empid
col2 Name
col3 N/A
col4 mailid
col5 mailid

请帮助实现此实用程序的任何指针。

2 个答案:

答案 0 :(得分:2)

要做到这样的分析,你需要一个完全成熟(T-)SQL语法分析器,它可以访问数据库(提示:列表达式可以得到任意复杂的,与子查询和一切)目前的结构。

更新:我在下面的查询计划的想法不起作用。虽然该计划很好地跟踪列引用,但它不会以正确的顺序显示输出列。哎呀!我现在无法看到它是如何治愈的,属性中没有序数。所以,抱歉,不起作用。我仍然留待参考,也许其他人有基于此的想法。


我想到的一件事就是查看查询计划。您必须解析XML计划以查看某个列的值的来源。虽然这可能比直接查看SQL更简单,但它仍然不是微不足道的。查询计划也会变得非常复杂。但为了说明这个原理,让我们看一下AdventureWorks DB上的类似查询:

SELECT 
  rowguid, 
  Left(JobTitle,3),
  'hardcoded string',
  BirthDate,
  Replace(BirthDate,'@xyz.com','') 
FROM 
  HumanResources.Employee

此语句的XML查询计划如下所示:

<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.2" Build="11.0.3128.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="1" StatementEstRows="290" StatementId="1" StatementOptmLevel="TRIVIAL" StatementSubTreeCost="0.00807444" StatementText="Select rowguid, Left(JobTitle,3),'hardcoded string',BirthDate,Replace(BirthDate,'@xyz.com','') FROM HumanResources.Employee" StatementType="SELECT" QueryHash="0x5F035E11344539B" QueryPlanHash="0x717B3D06C26C61ED" RetrievedFromCache="false">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan CachedPlanSize="16" CompileTime="14" CompileCPU="12" CompileMemory="152">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="418321" EstimatedPagesCached="104580" EstimatedAvailableDegreeOfParallelism="2" />
            <RelOp AvgRowSize="4045" EstimateCPU="2.9E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="290" LogicalOp="Compute Scalar" NodeId="0" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="0.00807444">
              <OutputList>
                <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="BirthDate" />
                <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="rowguid" />
                <ColumnReference Column="Expr1003" />
                <ColumnReference Column="Expr1004" />
                <ColumnReference Column="Expr1005" />
              </OutputList>
              <ComputeScalar>
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Column="Expr1003" />
                    <ScalarOperator ScalarString="substring([AdventureWorks2012].[HumanResources].[Employee].[JobTitle],(1),(3))">
                      <Intrinsic FunctionName="substring">
                        <ScalarOperator>
                          <Identifier>
                            <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="JobTitle" />
                          </Identifier>
                        </ScalarOperator>
                        <ScalarOperator>
                          <Const ConstValue="(1)" />
                        </ScalarOperator>
                        <ScalarOperator>
                          <Const ConstValue="(3)" />
                        </ScalarOperator>
                      </Intrinsic>
                    </ScalarOperator>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Column="Expr1004" />
                    <ScalarOperator ScalarString="'hardcoded string'">
                      <Const ConstValue="'hardcoded string'" />
                    </ScalarOperator>
                  </DefinedValue>
                  <DefinedValue>
                    <ColumnReference Column="Expr1005" />
                    <ScalarOperator ScalarString="replace(CONVERT_IMPLICIT(varchar(40),[AdventureWorks2012].[HumanResources].[Employee].[BirthDate],121),'@xyz.com','')">
                      <Intrinsic FunctionName="replace">
                        <ScalarOperator>
                          <Convert DataType="varchar" Length="40" Style="121" Implicit="true">
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="BirthDate" />
                              </Identifier>
                            </ScalarOperator>
                          </Convert>
                        </ScalarOperator>
                        <ScalarOperator>
                          <Const ConstValue="'@xyz.com'" />
                        </ScalarOperator>
                        <ScalarOperator>
                          <Const ConstValue="''" />
                        </ScalarOperator>
                      </Intrinsic>
                    </ScalarOperator>
                  </DefinedValue>
                </DefinedValues>
                <RelOp AvgRowSize="80" EstimateCPU="0.000476" EstimateIO="0.00756944" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="290" LogicalOp="Clustered Index Scan" NodeId="1" Parallel="false" PhysicalOp="Clustered Index Scan" EstimatedTotalSubtreeCost="0.00804544" TableCardinality="290">
                  <OutputList>
                    <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="JobTitle" />
                    <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="BirthDate" />
                    <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="rowguid" />
                  </OutputList>
                  <IndexScan Ordered="false" ForcedIndex="false" ForceScan="false" NoExpandHint="false">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="JobTitle" />
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="BirthDate" />
                      </DefinedValue>
                      <DefinedValue>
                        <ColumnReference Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Column="rowguid" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[AdventureWorks2012]" Schema="[HumanResources]" Table="[Employee]" Index="[PK_Employee_BusinessEntityID]" IndexKind="Clustered" />
                  </IndexScan>
                </RelOp>
              </ComputeScalar>
            </RelOp>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>

在这里,SQL Server已经完成了解析SQL并确定列值最终来自哪里(然后优化计划,但这里没有兴趣)的所有艰苦工作。

第一个<OutputList>对应于SELECT中的列列表。它有5个列引用。从您的属性中可以看出,两个直接对应于表列,而其他三个只引用一些任意命名的表达式。现在你可以搜索这些表达式(如果需要的话递归),而这些表达式又有其他列引用(或者,如果只是引用常量的“Expr1004”),则可以查找。

所以,因为你只需要看看这个计划的几个要素,你必须追捕源列(注意,有可能是一个给定的输出列多个源列)的一个很好的机会。< / p>

要获取XML查询计划,只需执行

SET SHOWPLAN_XML ON
<your statement>
SET SHOWPLAN_XML OFF

输出是计划(不执行声明 - 它只是估计的计划,但这里并不重要)。

希望有所帮助。

答案 1 :(得分:0)

这样的东西?

Select Empid, Left(Name,3) as Name, 'hardcoded string' as [N/A], Mailid as mailid, Replace(Mailid,'@xyz.com','') as mailid2
from Employee