私は以前これに答えましたが、未知の量の「テキストセグメント」を処理するのに効率的なものを書くことはできませんでした。
私は[MAILCITY]フィールドをXMLノードに変更する方法を発見しました。それぞれの 'テキストセグメント'にxmlフィールド内の独自のノードが割り当てられています。次に、それらのxmlフィールドをノードごとに処理し、連結してからSQL varcharに戻すことができます。それは複雑ですが、うまくいきます。
CREATE TABLE
#masterfeelisting (
[MAILCITY] varchar(max) not null
);
INSERT INTO #masterfeelisting VALUES
('terra bellA')
,(' terrA novA ')
,('chicagO ')
,('bostoN')
,('porT dE sanTo')
,(' porT dE sanTo pallo ');
SELECT
RTRIM
(
(SELECT
UPPER([xmlField].[xmlNode].value('.', 'char(1)')) +
LOWER(STUFF([xmlField].[xmlNode].value('.', 'varchar(max)'), 1, 1, '')) + ' '
FROM [xmlNodeRecordSet].[nodeField].nodes('/N') as [xmlField]([xmlNode]) FOR
xml path(''), type
).value('.', 'varchar(max)')
) as [MAILCITY]
FROM
(SELECT
CAST('<N>' + REPLACE([MAILCITY],' ','</N><N>')+'</N>' as xml) as [nodeField]
FROM #masterfeelisting
) as [xmlNodeRecordSet];
Drop table #masterfeelisting;
まず、私はテーブルを作成し、ダミーの値でそれを埋める::)
ここではコードです。
は今ここにコードの美しさです:#masterfeelistingの各レコードに対して
、我々は各「テキストセグメント」のノードを持つXMLフィールドを作成しようとしています。
ie。'<N></N><N>terrA</N><N>novA</N><N></N>'
1)これが行われる方法(これは、VARCHAR 'TERRA NOVA' から構築される)は、REPLACE関数を使用することです。
文字列はノードの先頭を指定するために'<N>'
で始まります。その後:
REPLACE([MAILCITY],' ','</N><N>')
これは、効果的に全体[MAILCITY]文字列を通過し、'</N><N>'
で各 ' '
を置き換えた後、文字列が'</N>'
で終わります。ここで、'</N>'
は各ノードの終わりを示します。
これで、いくつかの空のノードを持つ美しいXML文字列と、「テキストセグメント」が自分のノードにうまく配置されました。すべての「スペース」が削除されました。
2)次に、文字列をxmlにキャストする必要があります。そしてそのフィールドに[nodeField]という名前をつけます。今度は、新しく作成したレコードセットでxml関数を使用できます。 (。便利な[xmlNodeRecordSet]という名前)
3)今、私たちはメイン、サブセレクト示すことによってに[xmlNodeRecordSet]を読むことができます:
FROM [xmlNodeRecordSet].[nodeField].nodes('/N')
これは、我々がノードとして[nodeField]を読んでいる私達に告げます'/N'
の区切り文字を使用します。
as [xmlField]([xmlNode]) FOR xml path(''), type
をこれは、それぞれ[xmlField】XML文字列内の各【にxmlNode]のために解析されることを意味する。
ノードフィールドのこのテーブルは、次に示すことによって解析されます。
4)だからで主副セレクト:
各ブランクノード'<N></N>'
が破棄されます。 (または処理されません)
'テキストセグメント'が含まれている各ノードが解析されます。すなわち<N>terrA</N>
UPPER([xmlField].[xmlNode].value('.', 'char(1)')) +
このコードは、フィールドの外に、各ノードを取得し、その内容'.'
を取り、最初の文字だけ'char(1)'
をつかむだろう。それは大文字の文字になります。 (末尾のプラス記号は、それがコードの次のビットでこの手紙を連結することを意味:
LOWER(STUFF([xmlField].[xmlNode].value('.', 'varchar(max)'), 1, 1, ''))
は今ここに美しさがある... STUFFがために、位置から、文字列を取る関数であります。長さ、および代替別の文字列
STUFF
だから、私たちの文字列です(文字列は、位置、長さ、置換文字列を開始):全体strinをつかむ
[xmlField].[xmlNode].value('.', 'varchar(max)')
gは現在のノードの内部では'varchar(max)'
なので、
開始位置は1です。長さは1です。置換文字列は''
です。これは効果的に最初の文字を何も置き換えずに取り除きます。したがって残りの文字列はすべて小文字にしたい他の文字です。だからこそ、私たちは何をしているのですか?我々はそれらをすべて小文字にするためにLOWER
を使用します。そして、この結果は、私たちがすでに大文字で書いていた最初の手紙と結びついています。
お待ちください...まだ完了していません...まだ+ ' '
を追加する必要があります。これは、大文字の 'テキストセグメント'の後に空白を追加します。このノードが完了した後にもう1つの「テキストセグメント」がある場合のみです。
このメインサブSelectは、[xmlField]内の各ノードを解析し、それらをすべてうまく連結します。
5)しかし、私たちは1つの大きなハッピーコンカチネーションがあるので、xmlフィールドからSQL varcharフィールドに戻す必要があります。したがって、メインのサブ選択の後には、
.value('.', 'varchar(max)')
が必要です。これにより、[MAILCITY]がSQLのvarcharに戻されます。
6)しかし、ホールド...私たちはまだ行われていません。我々はそれぞれの 'テキストセグメント'の最後に余分なスペースを入れていることを覚えていますか?さて、最後のテキストセグメントにはまだ余分なスペースがあります。だから我々はRTRIM
を使ってその空間を右にトリムする必要がある。
7)とバックas [MAILCITY]
8への最後のフィールドの名前を変更することを忘れてはいけない)そして、それはそれです。このコードは未知の量の「テキストセグメント」を取り、それらのそれぞれをフォーマットします。すべてXMLの楽しさを使用し、それはノードパーザーです。
役立ちます:)の
可能な重複・ホープ[SQL Serverの:適切なケース/タイトルケースにすべて大文字にします](http://stackoverflow.com/questions/230138/sql-server-make-all -upper-case-to-proper-case-title-case) – JNevill
これは実際には重複ではありません。スレッドには、部分文字列の数に制限がない場合の解決策があります。この問題は、より効率的に解決することができます。 –
(可能であれば)代わりに、アプリケーションコードでこのようなことを行うことを検討してください。 SQLは文字列の書式設定/処理ではあまり良くありません。 – Blorgbeard