3

SQL2008サーバーでトリガーを挿入する前に、値を解析するためのヘルプが必要です。

テキストフィールドを含むテーブルがあります(ソースと呼びましょう)。フィールド値は次のようになります

10-15、20-22、25-26、

そして、別のフィールド(たとえばターゲット)にコンマ区切りの値が必要です。

10,11,12,13,14,15,20,21,22,25,26、

これは、トリガーを挿入する前に実行できますか、それとも何らかの外部アプリが必要ですか?

ありがとうございました。

4

2 に答える 2

1

まず、を生成するための値を作成する必要Table Valued functionstartあります。これは、を使用して行われます。endsequencerecursive 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

あなたは範囲を取得してそれをに渡すことができるようにsplitsingle column入る必要がありますrowsfunction

 ;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として保存するのではなく、stringcolumnsrangeint

更新しました

同じページにいるだけです。Insert Trigger次のような値を含むソーステーブルで作成します10-15,20-22,25-26。これらの値をに変換してテーブルにsequence挿入する必要があります。Targetこの場合は、次のコードを使用できます。

基本的に、トリガーに論理テーブルであるデータを挿入するトリガーが作成されますDerived Table次に、上記を使用して、テーブルにを挿入します。insertednested CTE'ssequencetarget

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
于 2013-03-25T13:35:05.123 に答える
0

これらの数値は、実際には別のテーブルに格納することをお勧めします。たとえば、範囲(start int、end int)と、参照するテーブルへのmany-1リンクを指定します。これにより、このようなクエリがはるかに簡単になり、他の潜在的な頭痛の種を減らすことができます。しかし、多分あなたはそれをこのようにする正当な理由があります。その場合、CSV文字列を生成するUDFを作成し、フィールドをUDFを参照する計算列として宣言することをお勧めします。ただし、これが頻繁に使用されるテーブルまたは頻繁に更新されるテーブルである場合は、潜在的なパフォーマンスの問題に注意してください。

于 2013-03-25T12:50:12.887 に答える