如何解决标准化大写的字符串,但括号中的内容保持不变
我想在数据库中输入一个适当的字符串,但是我在使用ProperCase存储过程时遇到问题。
要解决以下问题,我需要使用toupper功能修复括号中的内容。我正在使用sql Server 2017。
我希望我的程序处于我可以重用的函数中。这也需要在2016年生效
TEST DATA (BA1)
TEST DATA 2 (BA2)
TEST DATA 3 (BA3)
它应该返回
Test Data (BA1)
Test Data 2 (BA2)
Test Data 3 (BA3)
但是它正在返回:
Test Data (Ba1)
Test Data 2 (Ba2)
Test Data 3 (Ba3)
有什么想法可以阻止它变成小写吗?因此,我的意思是(左括号和右括号中的内容应保持大写或变为大写)
问题出现在括号中(这也会使A小写)。我希望函数忽略括号内的文本。
IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE
(@str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
SET @str = ' ' + @str
SET @str = 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( @str,' a',' A'),' b',' B'),' c',' C'),' d',' D'),' e',' E'),' f',' F'),' g',' G'),' h',' H'),' i',' I'),' j',' J'),' k',' K'),' l',' L'),' m',' M'),' n',' N'),' o',' O'),' p',' P'),' q',' Q'),' r',' R'),' s',' S'),' t',' T'),' u',' U'),' v',' V'),' w',' W'),' x',' X'),' y',' Y'),' z',' Z')
RETURN RIGHT(@str,LEN(@str) - 1)
END
GO
编辑2
我也尝试过以下最佳答案,但结果相同
SQL: capitalize first letter only
CREATE FUNCTION [dbo].[CapitalizefirstLetter]
(
--string need to format
@string VARCHAR(200)--increase the variable size depending on your needs.
)
RETURNS VARCHAR(200)
AS
BEGIN
--Declare Variables
DECLARE @Index INT,@ResultString VARCHAR(200)--result string size should equal to the @string variable size
--Initialize the variables
SET @Index = 1
SET @ResultString = ''
--Run the Loop until END of the string
WHILE (@Index <LEN(@string)+1)
BEGIN
IF (@Index = 1)--first letter of the string
BEGIN
--make the first letter capital
SET @ResultString =
@ResultString + UPPER(SUBSTRING(@string,@Index,1))
SET @Index = @Index+ 1--increase the index
END
-- IF the prevIoUs character is space or '-' or next character is '-'
ELSE IF ((SUBSTRING(@string,@Index-1,1) =' 'or SUBSTRING(@string,1) ='-' or SUBSTRING(@string,@Index+1,1) ='-') and @Index+1 <> LEN(@string))
BEGIN
--make the letter capital
SET
@ResultString = @ResultString + UPPER(SUBSTRING(@string,1))
SET
@Index = @Index +1--increase the index
END
ELSE-- all others
BEGIN
-- make the letter simple
SET
@ResultString = @ResultString + LOWER(SUBSTRING(@string,1))
SET
@Index = @Index +1--incerase the index
END
END--END of the loop
IF (@@ERROR
<> 0)-- any error occur return the sEND string
BEGIN
SET
@ResultString = @string
END
-- IF no error found return the new string
RETURN @ResultString
END
但是我尝试使用以下内容。
Create FUNCTION [dbo].[ProperCase2]
(@str VARCHAR(MAX))
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @keysValuetoSearch NVARCHAR(4000) = '('
DECLARE @untilThisCharappears NVARCHAR(4000) = ')'
DECLARE @keysValuetoSearchPattern NVARCHAR(4000) = '%' + @keysValuetoSearch + '%'
DECLARE @leftString NVARCHAR(4000)
DECLARE @Length INT
DECLARE @test NVARCHAR(4000)
DECLARE @lhb NVARCHAR(4000)
SET @lhb = SUBSTRING(
@str,PATINDEX(@keysValuetoSearchPattern,@str) + LEN(@keysValuetoSearch),CHARINDEX(
@untilThisCharappears,@str,@str) + LEN(@keysValuetoSearch)
) -(PATINDEX(@keysValuetoSearchPattern,@str) + LEN(@keysValuetoSearch))
);
SET @Length = CHARINDEX(@keysValuetoSearch,@str)
set @leftString= SUBSTRING(@str,1,CASE WHEN @Length - 1 < 0
THEN LEN(@str)
ELSE @Length - 1 END)
RETURN dbo.CapitalizefirstLetter(@LeftString) + ' (' +@lhb + ')'
END
我收到以下错误
当我通过以下测试数据
SELECT dbo.ProperCase2('Test DBA (BA1)') AS Test1
SELECT dbo.ProperCase2('Test DBA EA1') AS Test2
(受影响的1行)消息537,级别16,状态3,第4行无效长度 参数传递给LEFT或SUBSTRING函数。
解决方法
这不是理想的解决方案,但它似乎可以工作。我在这里使用了两个内联表值函数。标量函数通常不像行内表值函数那样在任何地方执行,尽管2019支持标量内联,但您使用的是2017。
首先,您需要获取DelimitedSplit8K_LEAD
的副本,因为我们需要一个支持顺序位置的分隔符(STRING_SPLIT
不支持)。然后,我们可以使用一些窗口式SUM
来检查括号的数量。如果我们处于正面,则我们位于方括号内,不应使用“适当”的大写字母。我还假定,在括号后可能有数据 ,否则实际上会更容易:这给出了以下内容:
USE Sandbox;
GO
CREATE OR ALTER FUNCTION dbo.ProperCase (@String varchar(8000))
RETURNS table
AS RETURN
WITH Split AS(
SELECT DS.ItemNumber,DS.Item,SUM(CASE CHARINDEX('(',DS.Item) WHEN 0 THEN 0 ELSE 1 END) OVER (ORDER BY DS.ItemNumber ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) -
ISNULL(SUM(CASE CHARINDEX(')',DS.Item) WHEN 0 THEN 0 ELSE 1 END) OVER (ORDER BY DS.ItemNumber ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS InBrackets
FROM dbo.DelimitedSplit8K_LEAD(@String,' ') DS)
SELECT STRING_AGG(CASE S.InBrackets WHEN 0 THEN STUFF(LOWER(S.Item),1,UPPER(LEFT(S.Item,1))) ELSE S.Item END,' ') WITHIN GROUP (ORDER BY S.ItemNumber) AS NewString
FROM Split S;
GO
SELECT *
FROM (VALUES('TEST DATA (BA1)'),('TEST DATA 2 (BA2)'),('TEST DATA 3 (BA3)'),('TEST DATA 4 (BA4) TEST'))V(YourString)
CROSS APPLY dbo.ProperCase(V.YourString);
GO
,
如果您知道只有一组paren,并且在末尾,则可以拆分字符串,第一部分用适当的大小写,第二部分用glom返回。像这样:
BEGIN
SET @newstr = ' ' + LEFT(@str,CHARINDEX('(',@str);
SET @newstr = 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( @str,' a',' A'),' b',' B'),' c',' C'),' d',' D'),' e',' E'),' f',' F'),' g',' G'),' h',' H'),' i',' I'),' j',' J'),' k',' K'),' l',' L'),' m',' M'),' n',' N'),' o',' O'),' p',' P'),' q',' Q'),' r',' R'),' s',' S'),' t',' T'),' u',' U'),' v',' V'),' w',' W'),' x',' X'),' y',' Y'),' z',' Z')
RETURN STUFF(@newstr,'') + RIGHT(@str,REVERSE(@str))
END;
注意:这是一个非常具体的答案,可以根据您输入的内容来破解当前功能。
通常,我建议您重写该函数以逐个字符地遍历字符串,以便跟踪多个括号表达式。
,您可以仅使用SQL来执行此操作,而无需任何过程。
WITH
-- your input
indata(s) AS (
SELECT 'TEST DATA (BA1)'
UNION ALL SELECT 'TEST DATA 2 (BA2)'
UNION ALL SELECT 'TEST DATA 3 (BA3)'
),-- add an identifier,which you need for grouping later ...
w_id AS (
SELECT
ROW_NUMBER() OVER(ORDER BY s) AS id,*
FROM indata
),-- "explode" into one row per space delimited sub-string using STRING_SPLIT() ...
words AS (
SELECT
id,value
FROM w_id
CROSS APPLY STRING_SPLIT(s,' ')
),-- check if the "value" you got begins with a left paren
-- and ends with a right paren,and proceed accordingly ...
right_case AS (
SELECT
id,CASE WHEN LEFT(value,1) <> '(' AND RIGHT(value,1) <> ')'
THEN UPPER(LEFT(value,1))+LOWER(RIGHT(value,LEN(value)-1))
ELSE value
END AS val
FROM words
)
-- finally,re-aggregate all together ...
SELECT
STRING_AGG(val,' ') AS s
FROM right_case
GROUP BY id;
s
Test Data (BA1)
Test Data 2 (BA2)
Test Data 3 (BA3)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。