ใช้อักษรตัวแรกของแต่ละคำของแต่ละประโยคใน SQL Server


18

ฉันต้องการใช้อักษรตัวแรกของแต่ละคำของแต่ละประโยคในคอลัมน์ SQL

ตัวอย่างเช่นถ้าประโยคคือ:

'ฉันชอบภาพยนตร์'

แล้วฉันต้องการผลลัพธ์:

'ฉันชอบหนัง'

ค้นหา:

declare @a varchar(15) 

set @a = 'qWeRtY kEyBoArD'

select @a as [Normal text],
upper(@a) as [Uppercase text],
lower(@a) as [Lowercase text],
upper(left(@a,1)) + lower(substring(@a,2,len(@a))) as [Capitalize first letter only]

ที่นี่ฉันเขียนอักษรตัวแรกตัวบนล่างและพิมพ์ใหญ่ในคอลัมน์ของฉันเท่านั้น (ที่นี่ฉันใส่คำแบบสุ่ม)

นี่คือผลลัพธ์ของฉัน:

ป้อนคำอธิบายรูปภาพที่นี่

มีความเป็นไปได้ที่จะทำเช่นนั้น?

ความเป็นไปได้ใด ๆ ที่จะได้ผลลัพธ์โดยไม่ต้องใช้ฟังก์ชั่นที่ผู้ใช้กำหนด?

ฉันต้องการผลลัพธ์ Qwerty Keyboard


11
ทำไมคุณต้องการทำเช่นนี้ภายในเซิร์ฟเวอร์ sql เลเยอร์การนำเสนอของคุณควรจัดการอย่างมีประสิทธิภาพ!
Kin Shah

คุณไม่มีเลเยอร์การนำเสนอเสมอเช่นเมื่อล้างข้อมูลที่ไม่ถูกต้องที่นำเข้าสู่ SQL Server และคุณไม่ต้องการเขียนโปรแกรม C # เพื่อทำ ใช่คุณสามารถลงทุนในฟังก์ชั่น CLR แต่สิ่งที่รวดเร็วและสกปรกที่ทำงาน
Jeffrey Roughgarden

คำตอบ:


26
declare @a varchar(30); 

set @a = 'qWeRtY kEyBoArD TEST<>&''"X';

select stuff((
       select ' '+upper(left(T3.V, 1))+lower(stuff(T3.V, 1, 1, ''))
       from (select cast(replace((select @a as '*' for xml path('')), ' ', '<X/>') as xml).query('.')) as T1(X)
         cross apply T1.X.nodes('text()') as T2(X)
         cross apply (select T2.X.value('.', 'varchar(30)')) as T3(V)
       for xml path(''), type
       ).value('text()[1]', 'varchar(30)'), 1, 1, '') as [Capitalize first letter only];

นี่เป็นครั้งแรกแปลงสตริงเพื่อ XML <X/>โดยการแทนที่ช่องว่างทั้งหมดที่มีแท็กที่ว่างเปล่า จากนั้นก็จะ shreds XML nodes()ที่จะได้รับหนึ่งคำต่อแถวใช้ ในการรับแถวกลับเป็นค่าเดียวจะใช้for xml pathเคล็ดลับ


8
และรหัสนั้นเป็นเหตุผลที่ฉันจะไม่ทำอย่างนั้นใน SQL ไม่ได้บอกว่าคำตอบนั้นผิด - มันถูกถาม แต่ SQL มาตรฐานนั้นไม่เหมาะสำหรับการจัดการสตริงประเภทนี้ ฟังก์ชั่นที่ใช้ CLR จะทำงานได้หรือเพียงแค่ทำในชั้นนำเสนอ
TomTom

8
@TomTom มันดูซับซ้อน แต่ก็ไม่มีอะไรเทียบได้กับเคียวรีแผนที่สร้างขึ้นและจะไม่รวดเร็วตามมาตรฐานใด ๆ อย่างไรก็ตามมันเป็นเรื่องเกี่ยวกับการศึกษาและความสนุกสนานในการขุดลงไปในสิ่งที่เกิดขึ้นจริงในการสืบค้นและทำไมมันถูกเขียนขึ้นในแบบที่เป็น ปัญหาสามารถแก้ไขได้ด้วยฟังก์ชั่นแบ่งสตริง (ตารางตัวเลข) ยากที่จะหลีกเลี่ยงfor xml pathเคล็ดลับในการเรียงต่อกัน ถ้าคุณไม่ใช้ CLR ซึ่งจะเป็นตัวเลือกที่ดีที่สุดหากความเร็วและประสิทธิภาพเป็นสิ่งสำคัญ
Mikael Eriksson

15

ใน SQL Server 2016 คุณสามารถทำได้ด้วย R เช่น

-- R capitalisation code stolen from here:
-- http://stackoverflow.com/questions/6364783/capitalize-the-first-letter-of-both-words-in-a-two-word-string

EXEC sp_execute_external_script
    @language = N'R',
    @script = N'
simpleCap <- function(x) {
  s <- strsplit(x, " ")[[1]]
  paste(toupper(substring(s, 1,1)), substring(s, 2),
        sep="", collapse=" ")
}             

OutputDataSet <- as.data.frame((sapply(as.vector(InputDataSet$xtext), simpleCap)))',
    @input_data_1 = N'SELECT LOWER(testString) xtext FROM dbo.testStrings'
WITH RESULT SETS ( ( properCase VARCHAR(50) NOT NULL ) );

ไม่ว่าคุณควรหรือไม่ก็เป็นคำถามที่แตกต่าง:)


โอ้คุณไม่ควรแน่นอน บางครั้งมันเป็นตัวเลือกที่แย่ที่สุดหรืออย่างที่ OP บอกไว้พวกเขาต้องการความรวดเร็วและสกปรก
Jonathan Fite

12

บางทีฉันโง่ แต่กำลังตรวจสอบข้อความค้นหาด้านล่างที่ฉันเขียนกับข้อความที่ให้มาบางรายการดูเหมือนว่าจะมีประสิทธิภาพมากกว่านี้เล็กน้อย (ขึ้นอยู่กับการจัดทำดัชนี)

รหัสนั้นโง่เล็กน้อย แต่ไม่มีการบอกว่าถ้ามันดูโง่ แต่มันก็ใช้งานได้มันก็ไม่ได้โง่

Begin

    Declare @text Varchar(30);

    Set @text = 'qWeRtY kEyBoArD TEST<>&''"X';

    Declare @1 Varchar(2)= ' a'
      , @2 Varchar(2)= ' b'
      , @3 Varchar(2)= ' c'
      , @4 Varchar(2)= ' d'
      , @5 Varchar(2)= ' e'
      , @6 Varchar(2)= ' f'
      , @7 Varchar(2)= ' g'
      , @8 Varchar(2)= ' h'
      , @9 Varchar(2)= ' i'
      , @10 Varchar(2)= ' j'
      , @11 Varchar(2)= ' k'
      , @12 Varchar(2)= ' l'
      , @13 Varchar(2)= ' m'
      , @14 Varchar(2)= ' n'
      , @15 Varchar(2)= ' o'
      , @16 Varchar(2)= ' p'
      , @17 Varchar(2)= ' q'
      , @18 Varchar(2)= ' r'
      , @19 Varchar(2)= ' s'
      , @20 Varchar(2)= ' t'
      , @21 Varchar(2)= ' u'
      , @22 Varchar(2)= ' v'
      , @23 Varchar(2)= ' w'
      , @24 Varchar(2)= ' x'
      , @25 Varchar(2)= ' y'
      , @26 Varchar(2)= ' z';

Set @text=' '+@text

    Select  LTrim(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Lower(@text) ,
                                                              @1 , Upper(@1)) ,
                                                              @2 , Upper(@2)) ,
                                                              @3 , Upper(@3)) ,
                                                              @4 , Upper(@4)) ,
                                                              @5 , Upper(@5)) ,
                                                              @6 , Upper(@6)) ,
                                                              @7 , Upper(@7)) ,
                                                              @8 , Upper(@8)) ,
                                                              @9 , Upper(@9)) ,
                                                              @10 , Upper(@10)) ,
                                                              @11 , Upper(@11)) ,
                                                              @12 , Upper(@12)) ,
                                                              @13 , Upper(@13)) ,
                                                              @14 , Upper(@14)) ,
                                                              @15 , Upper(@15)) ,
                                                              @16 , Upper(@16)) ,
                                                              @17 , Upper(@17)) ,
                                                              @18 , Upper(@18)) ,
                                                              @19 , Upper(@19)) ,
                                                              @20 , Upper(@20)) ,
                                                            @21 , Upper(@21)) ,
                                                    @22 , Upper(@22)) , @23 ,
                                            Upper(@23)) , @24 , Upper(@24)) ,
                            @25 , Upper(@25)) , @26 , Upper(@26)));


end

2
นี่คือคำตอบที่ดีและน่ากลัว ฉันชอบพื้นที่โดยเฉพาะอย่างยิ่งที่คุณถูกตรึงไว้ที่จุดเริ่มต้นแล้วดึงออกในตอนท้าย
BradC

2
@BradC มันน่ากลัว แต่เมื่อฉันลองเปรียบเทียบกับวิธี XML กับชุดข้อมูลดูเหมือนว่าจะทำงานด้วยค่าใช้จ่ายเพียงเล็กน้อย!
Chris J

9

อีกทางเลือกหนึ่งคือการจัดการผ่าน SQLCLR มีแม้แต่วิธีที่มีอยู่แล้วใน. NET ที่ทำสิ่งนี้: TextInfo.ToTitleCase (ในSystem.Globalization ) วิธีนี้จะพิมพ์ใหญ่ตัวอักษรตัวแรกของแต่ละคำและตัวพิมพ์เล็กเป็นตัวอักษรที่เหลือ แตกต่างจากข้อเสนออื่น ๆ ที่นี่มันยังข้ามคำที่อยู่ในทุกกรณีบนสมมติว่าพวกเขาเป็นคำย่อ แน่นอนว่าหากต้องการพฤติกรรมนี้มันจะง่ายพอที่จะอัปเดตคำแนะนำ T-SQL ใด ๆ เพื่อทำสิ่งนี้เช่นกัน

ข้อดีอย่างหนึ่งของวิธีการ. NET คือสามารถใช้ตัวอักษรตัวพิมพ์ใหญ่ที่เป็นอักขระเสริมได้ ตัวอย่างเช่น: DESERET SMALL LETTER OWมีการแมปตัวพิมพ์ใหญ่ของDESERET CAPITAL LETTER OW (ทั้งคู่แสดงเป็นกล่องเมื่อฉันวางมันลงที่นี่)แต่UPPER()ฟังก์ชั่นไม่เปลี่ยนเวอร์ชั่นตัวพิมพ์เล็กเป็นตัวพิมพ์ใหญ่ถึงแม้ว่า Latin1_General_100_CI_AS_SCการเปรียบเทียบค่าเริ่มต้นสำหรับฐานข้อมูลปัจจุบันกำหนดให้ ดูเหมือนว่าจะสอดคล้องกับเอกสาร MSDN ซึ่งไม่ได้แสดงไว้UPPERและLOWERในแผนภูมิของฟังก์ชันที่ทำงานแตกต่างกันเมื่อใช้_SCCollation: Collation และ Unicode Support: อักขระเพิ่มเติม

SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]

คืนค่า (ขยายเพื่อให้คุณเห็นอักขระเสริมจริง ๆ ):

ผลการค้นหาที่แสดง UPPER () ไม่ทำงานกับอักขระเสริม

คุณสามารถดูรายการอักขระ (และปัจจุบัน) ทั้งหมดที่เป็นตัวพิมพ์เล็กและเปลี่ยนเป็นตัวพิมพ์ใหญ่โดยใช้คุณสมบัติการค้นหาต่อไปนี้ที่ Unicode.org (คุณสามารถดูอักขระเสริมได้โดยเลื่อนลงไปจนกว่าจะถึง "DESERET" หรือเพียงกดControl-Fและค้นหาคำนั้น):

http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D

แม้ว่าจะซื่อสัตย์ แต่ก็ไม่ได้เป็นประโยชน์อย่างมากเพราะเป็นที่น่าสงสัยว่าใครก็ตามที่ใช้อักขระเสริมที่สามารถใส่ชื่อเรื่องได้ ไม่ว่าจะด้วยวิธีใดก็ตามนี่คือรหัส SQLCLR:

using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;

public class TitleCasing
{
    [return: SqlFacet(MaxSize = 4000)]
    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
    {
        TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
        return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
    }
}

นี่คือคำแนะนำของ @ MikaelEriksson - แก้ไขเล็กน้อยเพื่อจัดการNVARCHARข้อมูลรวมถึงข้ามคำที่เป็นตัวพิมพ์ใหญ่ทั้งหมด (เพื่อให้ตรงกับพฤติกรรมของวิธีการ. NET มากขึ้น) - พร้อมกับการทดสอบการใช้ T-SQL และ การใช้งาน SQLCLR:

SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);

SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
         + NCHAR(0xD801)+NCHAR(0xDC28)
         + N'pPLe '
         + NCHAR(0x24D0) -- ⓐ  Circled "a"
         + NCHAR(0xFF24) -- D  Full-width "D"
         + N'D u'
         + NCHAR(0x0308) -- ̈  (combining diaeresis / umlaut)
         + N'vU'
         + NCHAR(0x0308) -- ̈  (combining diaeresis / umlaut)
         + N'lA';
SELECT @a AS [Original];

SELECT STUFF((
       SELECT N' '
              + IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2, 
                    UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
                    + LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
                    T3.V)
       FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
                    AS XML).query('.')) AS T1(X)
       CROSS APPLY T1.X.nodes('text()') AS T2(X)
       CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
       FOR XML PATH(''), TYPE
       ).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
                AS [Capitalize first letter only];

SELECT dbo.TitleCase(@a) AS [ToTitleCase];

ผลการสืบค้นแสดงผลลัพธ์ของรหัส T-SQL XML และ ToTitleCase ผ่าน SQLCLR

ความแตกต่างในพฤติกรรมคือการใช้ T-SQL นี้แยกเฉพาะในพื้นที่เท่านั้นในขณะที่ ToTitleCase()วิธีการพิจารณาที่ไม่ใช่ตัวอักษรส่วนใหญ่จะเป็นตัวแยกคำ (ดังนั้นความแตกต่างในการจัดการส่วน "หนึ่ง & สอง")

การใช้งานทั้งสองจัดการลำดับการรวมอย่างถูกต้อง ตัวอักษรเน้นเสียงแต่ละตัวใน "üvÜlA" ประกอบด้วยตัวอักษรฐานและ diaeresis รวม / umlaut (จุดทั้งสองด้านบนตัวอักษรแต่ละตัว) และพวกเขาจะถูกแปลงเป็นกรณีอื่นอย่างถูกต้องในการทดสอบทั้งสอง

ในที่สุดข้อเสียเปรียบอย่างหนึ่งที่ไม่คาดคิดของรุ่น SQLCLR คือในการทดสอบหลายครั้งฉันพบข้อบกพร่องในรหัส. NET ที่เกี่ยวข้องกับการจัดการ Circled Letters (ซึ่งตอนนี้ได้รับการรายงานบน Microsoft Connect - อัพเดต: การเชื่อมต่อได้รับ ย้ายไปที่/dev/null- แท้จริง - ดังนั้นฉันอาจต้องส่งอีกครั้งหากปัญหายังคงมีอยู่) . NET library ปฏิบัติต่อ Circled Letters เป็นตัวคั่นคำซึ่งเป็นสาเหตุที่ไม่เปลี่ยน "ⓐDD" เป็น "Ⓐdd" เท่าที่ควร


FYI

ฟังก์ชั่น SQLCLR ที่ทำไว้ล่วงหน้าซึ่งห่อหุ้มTextInfo.ToTitleCaseวิธีที่กล่าวถึงข้างต้นนั้นมีอยู่ในรุ่นฟรีของSQL # (ซึ่งฉันเขียน) เป็นString_ToTitleCaseและString_ToTitleCase4k String_ToTitleCase4k

😺


5

เป็นทางเลือกแทนคำตอบของ Mikael Erikssonคุณสามารถพิจารณาใช้การจัดการตัวแปร T-SQL ที่เป็นกรรมสิทธิ์ของการตั้งค่าตัวแปรในคำสั่งเลือกหลายแถว

ใน SQL Server เมื่อตัวแปรถูกตั้งค่าเป็นส่วนหนึ่งของคำสั่ง SELECT แต่ละแถวจะดำเนินการวนซ้ำของชุดตรรกะ

ผู้คนมักใช้วิธีนี้ในการเชื่อมสตริงแม้ว่ามันจะไม่ได้รับการสนับสนุนและมีปัญหาบางอย่างที่ทำเป็นเอกสารอย่างเป็นทางการบางประเด็นที่ได้รับการบันทึกอย่างเป็นทางการกับมันปัญหาอย่างเป็นทางการเกี่ยวข้องกับลักษณะการสั่งซื้อโดยเฉพาะและเราไม่ต้องการที่นี่ดังนั้นอาจเป็นตัวเลือกที่ปลอดภัย

ที่นี่เราทำซ้ำตัวอักษรมากกว่า 26 ตัวและแทนที่ด้วยตัวพิมพ์ใหญ่หากตัวอักษรเว้นวรรค (เราเตรียมสตริงในตอนแรกโดยการใช้อักษรตัวแรกและพิมพ์ตัวพิมพ์เล็กตามที่คุณทำในคำถามของคุณ)

SQL มีความซับซ้อนเล็กน้อยเนื่องจากต้องการการใช้ Tally Table - ตารางตัวเลข - เพื่อสร้างการวนซ้ำ 26 ครั้งเพื่อแทนที่สิ่งที่มันกำลังทำอยู่ คุณสามารถสร้างฟังก์ชั่นที่ผู้ใช้กำหนดด้วยตาราง (TVF) แบบอินไลน์ได้อย่างสะดวกเพื่อสร้างตารางตัวเลขหรือคุณอาจใช้ตารางฟิสิคัล

ข้อเสียเปรียบของตัวเลือกนี้คือไม่สามารถเป็นส่วนหนึ่งของ inline TVF เนื่องจากจำเป็นต้องมีการตั้งค่าตัวแปร ดังนั้นหากคุณต้องการใช้วิธีนี้กับคอลัมน์ของเอาต์พุตของคุณคุณจะต้องห่อมันไว้ในคำสั่ง TVF แบบหลายคำสั่งหรือฟังก์ชันที่ผู้ใช้กำหนดแบบสเกลาร์

อย่างไรก็ตามแผนการสืบค้นนั้นง่ายกว่ามากและอาจเร็วกว่าวิธี XML อย่างมาก คุณสามารถโต้แย้งได้ง่ายขึ้นเช่นกัน (โดยเฉพาะถ้าคุณมีตารางคะแนนของคุณเอง)

DECLARE
    @a VARCHAR(15) = 'qWeRtY kEyBoArD';

SELECT
    @a = UPPER(LEFT(@a,1)) + LOWER(SUBSTRING(@a,2,LEN(@a)));

WITH TallyTableBase AS
(
    SELECT
        0 AS n
    FROM    (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS t(n)
)
SELECT
    @a = REPLACE(@a, ' ' + CHAR(n.n), ' ' + CHAR(n.n))
FROM        (
                SELECT      TOP 26 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) + 64 AS n
                FROM        TallyTableBase a
                CROSS JOIN  TallyTableBase b
            ) AS n;

SELECT
    @a AS [NewValue];

(ฉันทดสอบโดยใช้สตริงที่มีขนาดใหญ่กว่าและประมาณ 6ms กับ 14ms สำหรับโซลูชัน XML)

มีข้อ จำกัด เพิ่มเติมจำนวนมากสำหรับโซลูชันนี้ ตามที่เขียนไว้จะถือว่ามีการเปรียบเทียบที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่แม้ว่าคุณสามารถกำจัดปัญหานั้นได้โดยการระบุการเรียงหน้าหรือเรียกใช้ LCASE ในคำค้นหาในราคาที่มีประสิทธิภาพ นอกจากนี้ยังเน้นเฉพาะตัวอักษร ASCII มาตรฐานและอาศัยตำแหน่งในชุดอักขระดังนั้นมันจะไม่ทำอะไรกับñ


3

สมมติว่าคุณกำลังมองหาการใช้ประโยชน์จากคำตามช่องว่างนี่เป็นอีกวิธีหนึ่งที่คุณทำได้

DECLARE @String VARCHAR(1000)
SET @String = 'qWeRtY kEyBoArD tEst'

/*
Set the string to all lower case and
add a space at the beginning to ensure
the first letter gets capitalized
in the CTE
*/
SET @String = LOWER(' ' + @String)  

/*
Use a Tally "Table" as a means of
replacing the letter after the space
with the capitalize version of the
letter
*/
;WITH TallyTable
AS
(
    SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as N
    FROM master.sys.all_columns a CROSS JOIN master.sys.all_columns b

)
SELECT @String = REPLACE(@String,SUBSTRING(@String,CHARINDEX(' ',@String,N), 2),UPPER(SUBSTRING(@String,CHARINDEX(' ',@String,N), 2)))
FROM TallyTable
WHERE CHARINDEX(' ',@String,N) <> 0

--Remove the space added to the beginning of the string earlier
SET @String = RIGHT(@String,LEN(@String) - 1)

1

อาจไม่ได้เป็นหลักฐานกระสุน แต่ฉันหวังว่ามันจะเป็นประโยชน์ต่อเธรดนี้

DECLARE @t VARCHAR(50) = 'the quick brown fox jumps over the lazy dog', @i INT = 0

DECLARE @chk VARCHAR(1)

WHILE @i <= LEN(@t)
BEGIN
    SELECT @chk=SUBSTRING(@t,@i,1)
        IF @chk = CHAR(32)
        BEGIN
            SET @t = STUFF(@t,@i+1,1,UPPER(SUBSTRING(@t,@i+1,1)))
        END
    SET @i=@i+1
END
PRINT @t

0

ด้านล่างเป็นขั้นตอนที่ฉันใช้ในฐานข้อมูล Firebird เพื่อทำสิ่งนี้ อาจจะสามารถทำความสะอาดได้มาก แต่ก็ทำงานให้ฉันได้

set term ~;

Create Procedure EachWordCap

As

Declare Variable lcaption varchar(33);
Declare Variable lcurrentpos integer;
Declare Variable lstringlen integer;
begin
    for select ' ' || trim(lower(imagedata.imagename)) from imagedata
    where imagedata.imagename is not null and imagedata.imagename != ''
    into :lcaption
    do 
    begin
        lcurrentpos = 0;
        lstringlen = char_length(lcaption);
        while (lcurrentpos != 1) do
        begin
            lcurrentpos = position(' ', lcaption, iif(lcurrentpos = 0, 1,lcurrentpos)) + 1 ;
            lcaption = left(lcaption,lcurrentpos - 1) || upper(substring(lcaption from lcurrentpos for 1)) || right(lcaption,lstringlen - lcurrentpos);
        end
        --Put what you want to do with the text in here
    end
end~
set term ;~

0

CTE แบบเรียกซ้ำนั้นค่อนข้างดีสำหรับสิ่งประเภทนี้

อาจไม่ได้มีประสิทธิภาพโดยเฉพาะอย่างยิ่งสำหรับการดำเนินงานขนาดใหญ่ แต่จะช่วยให้การดำเนินการชนิดนี้ในคำสั่งเลือก SQL บริสุทธิ์:

declare @a varchar(100) 

set @a = 'tHe qUiCk bRoWn FOX jumps   OvEr The lAZy dOG';

WITH [CTE] AS (
  SELECT CAST(upper(Left(@a,1)) + lower(substring(@a,2,len(@a))) AS VARCHAR(100)) AS TEXT,
         CHARINDEX(' ',@a) AS NEXT_SPACE
  UNION ALL
  SELECT CAST(Left(TEXT,NEXT_SPACE) + upper(SubString(TEXT,NEXT_SPACE+1,1)) + SubString(TEXT,NEXT_SPACE+2,1000) AS VARCHAR(100)),
         CHARINDEX(' ',TEXT, NEXT_SPACE+1)
  FROM [CTE]
  WHERE NEXT_SPACE <> 0
)

SELECT TEXT
FROM [CTE]
WHERE NEXT_SPACE = 0

เอาท์พุท:

The Quick Brown Fox Jumps   Over The Lazy Dog

0

ฉันชอบรุ่นนี้ มันง่ายและสามารถใช้ในการสร้างฟังก์ชั่นคุณเพียงแค่ต้องมีรุ่นที่ถูกต้องของ SQL Server:

WITH words
AS (
    SELECT upper(left(Value, 1)) + lower(substring(Value, 2, len(Value))) AS word
    FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ')
    )
SELECT STRING_AGG(words.word, ' ')
FROM words

รุ่นใดที่เหมาะสม?
dezso

SQL Server (เริ่มต้นปี 2559)
Cristi

-2
DECLARE @someString NVARCHAR(MAX) = 'In this WHILE LOOP example' 

DECLARE @result NVARCHAR(MAX) =Upper(SUBSTRING(@someString, 1, 1))

DECLARE @index INT =2 

WHILE LEN(@someString)>@index

BEGIN

SET @result= @result+CASE WHEN CHARINDEX(' ',@someString,@index)<>0 THEN LOWER(SUBSTRING(@someString, @index, CHARINDEX(' ',@someString,@index)-@index+1)) +Upper(SUBSTRING(@someString, CHARINDEX(' ',@someString,@index)+1, 1)) ELSE  LOWER(SUBSTRING(@someString,@index, LEN(@someString) )) END

SET @index=CASE WHEN CHARINDEX(' ',@someString,@index)<>0 THEN CHARINDEX(' ',@someString,@index)+2 ELSE  LEN(@someString)+1  END

 END

SELECT  @result 

ฉันหวังว่าจะช่วย ...


ยินดีต้อนรับสู่ผู้ดูแลฐานข้อมูล! โปรดอธิบายว่าแบบสอบถามของคุณแก้ปัญหาของผู้เขียนอย่างไร คำตอบที่ไม่มีคำอธิบายโดยทั่วไปจะไม่ได้รับการตอบรับที่ดี
Glorfindel

-3

ทดสอบข้อมูล

declare @word varchar(100)
with good as (select 'good' as a union select 'nice' union select 'fine')
select @word = (SELECT TOP 1 a FROM good ORDER BY NEWID())

การดำเนินงาน

select substring(Upper(@word),1,1) + substring(@word, 2, LEN(@word))

การใช้อักษรตัวพิมพ์ใหญ่ซึ่งแยกกันอยู่แล้วนั้นง่าย ฉันเชื่อว่า OP มีความสนใจในการระบุคำภายในสตริงและใช้ประโยชน์จากแต่ละคำให้เป็นประโยชน์
Jon of All Trades
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.