SQL2008サーバーでトリガーを挿入する前に、値を解析するためのヘルプが必要です。
テキストフィールドを含むテーブルがあります(ソースと呼びましょう)。フィールド値は次のようになります
10-15、20-22、25-26、
そして、別のフィールド(たとえばターゲット)にコンマ区切りの値が必要です。
10,11,12,13,14,15,20,21,22,25,26、
これは、トリガーを挿入する前に実行できますか、それとも何らかの外部アプリが必要ですか?
ありがとうございました。
SQL2008サーバーでトリガーを挿入する前に、値を解析するためのヘルプが必要です。
テキストフィールドを含むテーブルがあります(ソースと呼びましょう)。フィールド値は次のようになります
10-15、20-22、25-26、
そして、別のフィールド(たとえばターゲット)にコンマ区切りの値が必要です。
10,11,12,13,14,15,20,21,22,25,26、
これは、トリガーを挿入する前に実行できますか、それとも何らかの外部アプリが必要ですか?
ありがとうございました。
まず、を生成するための値を作成する必要Table Valued function
がstart
あります。これは、を使用して行われます。end
sequence
recursive cte
CREATE FUNCTION FnGetRange(@startValue int,@endValue int)
RETURNS @rtnTable TABLE
(
generatedVal VARCHAR(MAX)
)
AS
BEGIN
;with cte(startValue,rangeVal,generatedVal)
as
(
Select @startValue,@endValue,@startValue as generatedVal
union all
Select startValue, rangeVal, generatedVal+1
from cte r
where rangeVal > generatedVal
)
Insert into @rtnTable
Select generatedVal from cte
return
END
あなたは範囲を取得してそれをに渡すことができるようにsplit
にsingle column
入る必要がありますrows
function
;with cte(range) as
(
SELECT
RIGHT(LEFT(T.rangeVal,Number-1),
CHARINDEX(',',REVERSE(LEFT(','+T.rangeVal,Number-1)))) as range
FROM
master..spt_values,
yourTable T
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(T.rangeVal)+1
AND
(SUBSTRING(T.rangeVal,Number,1) = ',' OR SUBSTRING(T.rangeVal,Number,1) = '')
)
基本的にmaster..spt_valuesを使用してシーケンスを生成する上記のソリューションがここに投稿されました
cteは次のような結果を返します
range
10-15
20-22
25-26
今、あなたsplit
は範囲に入る必要がStartValue
ありますEndValue
rangeCte (startValue,endValue) as
(
Select parsename(replace(range,'-','.'),2) as startValue,
parsename(replace(range,'-','.'),1) as endValue
from cte
)
上記は次のrangeCTE
ようなデータを返します
startValue endValue
10 15
20 22
25 26
これらの値を取得したら、FnGetRange
を使用して関数に渡す必要がありますcross apply
RowValue (rangeSep) as
( Select val.generatedVal as rangeSep from rangeCte r
CROSS APPLY
dbo.FnGetRange(r.StartValue,r.endValue) AS val
)
row
これによりシーケンスが生成されますが、複数の行になります。使い捨てに変換するにはxml path
SELECT STUFF(
(SELECT ',' + rangeSep
FROM RowValue
FOR XML PATH(''),type).value('.','varchar(max)'),1,1,'')
CTE's
最後のクエリをすべて組み合わせると、
;with cte(range) as
(
SELECT
RIGHT(LEFT(T.rangeVal,Number-1),
CHARINDEX(',',REVERSE(LEFT(','+T.rangeVal,Number-1)))) as range
FROM
master..spt_values,
yourTable T
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(T.rangeVal)+1
AND
(SUBSTRING(T.rangeVal,Number,1) = ',' OR SUBSTRING(T.rangeVal,Number,1) = '')
),rangeCte (startValue,endValue) as
(
Select parsename(replace(range,'-','.'),2) as startValue,
parsename(replace(range,'-','.'),1) as endValue
from cte
),RowValue (rangeSep) as
( Select val.generatedVal as rangeSep from rangeCte r
CROSS APPLY
dbo.FnGetRange(r.StartValue,r.endValue) AS val
)
SELECT STUFF(
(SELECT ',' + rangeSep
FROM RowValue
FOR XML PATH(''),type).value('.','varchar(max)'),1,1,'')
結果は次のようになります
10,11,12,13,14,15,20,21,22,25,26
他の人が示唆しているように、あなたは真剣に変更する必要があります。タイプのを保存するための作成table design
として保存するのではなく、string
columns
range
int
更新しました
同じページにいるだけです。Insert Trigger
次のような値を含むソーステーブルで作成します10-15,20-22,25-26
。これらの値をに変換してテーブルにsequence
挿入する必要があります。Target
この場合は、次のコードを使用できます。
基本的に、トリガーに論理テーブルであるデータを挿入するトリガーが作成されます。Derived Table
次に、上記を使用して、テーブルにを挿入します。inserted
nested CTE's
sequence
target
create trigger tri_inserts on a
after insert
as
set nocount on
Declare @RangeTable table
(rangeVal varchar(max))
Insert into @RangeTable
Select rangeColumn from INSERTED
;with cte(range) as
(
SELECT
RIGHT(LEFT(T.rangeVal,Number-1),
CHARINDEX(',',REVERSE(LEFT(','+T.rangeVal,Number-1)))) as range
FROM
master..spt_values,
@RangeTable T
WHERE
Type = 'P' AND Number BETWEEN 1 AND LEN(T.rangeVal)+1
AND
(SUBSTRING(T.rangeVal,Number,1) = ',' OR SUBSTRING(T.rangeVal,Number,1) = '')
),rangeCte (startValue,endValue) as
(
Select parsename(replace(range,'-','.'),2) as startValue,
parsename(replace(range,'-','.'),1) as endValue
from cte
),RowValue (rangeSep) as
( Select val.generatedVal as rangeSep from rangeCte r
CROSS APPLY
dbo.FnGetRange(r.StartValue,r.endValue) AS val
)
Insert into Target(DestColumn) --Change the target name
SELECT STUFF(
(SELECT ',' + rangeSep
FROM RowValue
FOR XML PATH(''),type).value('.','varchar(max)'),1,1,'')
GO
これらの数値は、実際には別のテーブルに格納することをお勧めします。たとえば、範囲(start int、end int)と、参照するテーブルへのmany-1リンクを指定します。これにより、このようなクエリがはるかに簡単になり、他の潜在的な頭痛の種を減らすことができます。しかし、多分あなたはそれをこのようにする正当な理由があります。その場合、CSV文字列を生成するUDFを作成し、フィールドをUDFを参照する計算列として宣言することをお勧めします。ただし、これが頻繁に使用されるテーブルまたは頻繁に更新されるテーブルである場合は、潜在的なパフォーマンスの問題に注意してください。