この種の分析を行うには、データベースの現在の構造にアクセスできる本格的な(T-)SQLパーサーが必要です(ヒント:列式は、副選択などで任意に複雑になる可能性があります)。
更新:クエリプランに関する以下の私のアイデアは機能しません。計画は列参照を適切にトレースしますが、出力列を正しい順序で表示しません。ARGH!現時点では、これがどのように修復されるかわかりません。属性には序数などがありません。だから、申し訳ありませんが、動作しません。私はまだそれを参照のために残します、多分誰か他の人がこれに基づいた考えを持っています。
頭に浮かぶことの1つは、クエリプランを確認することです。XMLプランを解析して、特定の列の値がどこから発生しているかを確認する必要があります。これはSQLを直接見るよりも簡単かもしれませんが、それでも簡単ではありません。クエリプランも非常に複雑になる可能性があります。しかし、原理を説明するために、AdventureWorksDBで同様のクエリを見てみましょう。
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を解析し、列の値が最終的にどこから来るかを決定するという大変な作業をすべて完了しています(そして、計画を最適化しますが、ここでは重要ではありません)。
1つ目<OutputList>
は、SELECTの列のリストに対応します。5つの列参照があります。2つは属性からわかるようにテーブル列に直接対応し、他の3つは任意の名前の式を参照するだけです。これで、これらの式を(必要に応じて再帰的に)探し出すことができます。これらの式には、他の列参照があります(または、定数を参照するだけの「Expr1004」の場合はそうではありません)。
したがって、計画のいくつかの要素を確認するだけでよいので、ソース列を探す可能性が高くなります(特定の出力列に複数のソース列がある場合があることに注意してください)。
XMLクエリプランを取得するには、実行するだけです
SET SHOWPLAN_XML ON
<your statement>
SET SHOWPLAN_XML OFF
出力は計画です(ステートメントを実行せずに-それは単なる推定計画ですが、ここでは重要ではありません)。
お役に立てば幸いです。