/ / SQL सर्वर के लिए कोई फ़ंक्शन है जिसने एक पैटर्न दिया है और एक मूल्य एक सामान्यीकृत मान लौटा सकता है - sql, फ़ंक्शन, डिज़ाइन-पैटर्न, sql-server-2008-r2

SQL सर्वर के लिए कोई फ़ंक्शन है जो एक पैटर्न और एक मान देता है एक सामान्यीकृत मान लौटा सकता है - sql, फ़ंक्शन, डिज़ाइन-पैटर्न, sql-server-2008-r2

मैं SQL 2008R2 में एक फ़ंक्शन प्रोग्रामिंग कर रहा हूँ iयह कुछ मान दे सकता है जैसे कि एक मान varchar, एक पैटर्न varchar, एक विभाजक चार और एक भराव भी char। फिर मैं "000.000.000.000", एक विभाजक के साथ "22687" मान देना चाहूंगा। " और भराव "0" होगा, तो मैं यह उम्मीद करना चाहूंगा कि फ़ंक्शन "000.000.022.687" लौटेगा, क्या किसी के पास पहले से कोई फ़ंक्शन है जो ऐसा कर सकता है?

कुछ इस तरह:

DECLARE @valor VARCHAR(30)
DECLARE @formato VARCHAR(30)
DECLARE @separador CHAR(1)
DECLARE @rellenarcon CHAR(1)

SELECT @valor       = "22959"
SELECT @formato     = "000.000.000.000"
SELECT @separador   = "."
SELECT @rellenarcon = "0"

DECLARE @n  INTEGER
DECLARE @m  INTEGER
DECLARE @i  INTEGER
DECLARE @j  INTEGER

SELECT @n   = LEN(@formato)
SELECT @m   = LEN(@valor)
SELECT @i   = 1
SELECT @j   = 1

DECLARE @res2 varchar(30)

SELECT @res2 = ""
SELECT @valor = REVERSE(@valor)

WHILE @i<=@n
BEGIN
if SUBSTRING(@formato,@i,1) <> @separador
begin
IF @j<=@m
BEGIN
SELECT @res2 = @res2 + SUBSTRING(@valor,@j,1)
SELECT @i=@i+1
SELECT @j=@j+1
END
ELSE
BEGIN
SELECT @res2 = @res2 + @rellenarcon
SELECT @i=@i+1
END
end
else
BEGIN
SELECT @res2 = @res2 + @separador
SELECT @i=@i+1
END
END

print reverse(@res2)

जावा से tsql के लिए एक क्रॉसओवर कोड है, जावा में मूल कोड है:

    public static String formatear(String valor, String formato, char separator,
char fillWith, Map<Integer, String> params) {

int n = formato.length() - 1;
int m = valor.length() - 1;
int i = n;
int j = m;

StringBuilder res = new StringBuilder(formato);

for(; i >= 0; i--) {
if(res.charAt(i) != separator) {
if(j >= 0) {
res.deleteCharAt(i);
res.insert(i, valor.charAt(j--));
} else {
res.deleteCharAt(i);
res.insert(i, fillWith);
}
}
}
if(params != null) {
Set<Integer> keys = params.keySet();

for(Integer key : keys) {
i = key;
res.deleteCharAt(i);
res.insert(i, params.get(key));
}
}

return res.toString();
}

उत्तर:

जवाब के लिए 0 № 1

निम्नलिखित अच्छी तरह से गठित इनपुट मानता है, उदा। मान पैटर्न से अधिक लंबा नहीं है।

declare @Pattern as VarChar(64) = "000.000.000.000";
declare @Fill as Char = "0";
declare @Value as VarChar(64) = "22687";
declare @False as Bit = 0;
declare @True as Bit = 1;

with Gargoyle as (
select @Pattern as Pattern, @Value as Value, Cast( "" as VarChar(64) ) as Buffer,
case when Right( @Pattern, 1 ) = @Fill then @True else @False end as Fill
union all
select
-- Always consume a character from the pattern.
Left( Pattern, Len( Pattern ) - 1 ),
-- Consume a character from the value if the pattern contains fill at the current position.
case
when Fill = @True and Value != "" then Left( Value, Len( Value ) - 1 )
else Value end,
-- Add the correct character to the buffer.
Cast( case when Fill = @True and Value != "" then Right( Value, 1 ) else Right( Pattern, 1 ) end + Buffer as VarChar(64) ),
-- Check the next pattern character for fill.
case
when Len( Pattern ) = 1 then @False
when Substring( Pattern, Len( Pattern ) - 1, 1 ) = @Fill then @True
else @False end
from Gargoyle
where Pattern != ""
)
select Buffer
from Gargoyle
where Pattern = "";

या, एक समारोह के रूप में:

create function dbo.PatternFill( @Pattern as VarChar(64), @Fill as Char, @Value as VarChar(64) )
returns VarChar(64)
as
begin
declare @Buffer as VarChar(64) = ""
declare @PatternChar as Char = Right( @Pattern, 1 )
declare @ValueChar as Char = Right( @Value, 1 )
while @Pattern != ""
begin
if @PatternChar = @Fill and @ValueChar != ""
begin
-- Replace a fill character with a value character.
select @Buffer = @ValueChar + @Buffer
if Len( @Value ) > 1
select @Value = Left( @Value, Len( @Value ) - 1 ), @ValueChar = Right( @Value, 1 )
else
select @ValueChar = "", @Value = ""
end
else
begin
-- Copy the pattern character.
select @Buffer = @PatternChar + @Buffer
end
if Len( @Pattern ) > 1
select @Pattern = Left( @Pattern, Len( @Pattern ) - 1 ), @PatternChar = Right( @Pattern, 1 )
else
select @PatternChar = "", @Pattern = ""
end
return @Buffer
end
go

declare @Result as VarChar(64)
declare @Count as Int = 1000000
declare @Start as DateTime = GetDate()
while @Count > 0
select @Result = dbo.PatternFill( "000.000.000.000", "0", "22687" ), @Count = @Count - 1
select @Result as [Result], DateDiff( ms, @Start, GetDate() ) as [Total ms]

मेरी नोटबुक पर 1,000,000 पुनरावृत्तियों में 151,656ms लगे, लेकिन यह "BOINCING" में व्यस्त है। यह एक खाली लूप द्वारा उपभोग किए गए समय के लिए कोई सुधार नहीं है या खाली फ़ंक्शन को कॉल करना है।


जवाब के लिए 0 № 2

यह प्रश्न यह करेगा:

;with cteZeroPadded(Num) as
(
Select  Right("000000000000" + "22687", 12)
)
,cteSplit as
(
Select  SUBSTRING(Num, 1, 3) Col1
,SUBSTRING(Num, 4, 3) Col2
,SUBSTRING(Num, 7, 3) Col3
,SUBSTRING(Num, 10, 3) Col4
From    cteZeroPadded
)
Select  Col1 + "." + Col2 + "." + Col3 + "." + Col4
From    cteSplit

जवाब के लिए 0 № 3

SQLServer2005 + में आप पुनरावर्ती के साथ विकल्प का उपयोग कर सकते हैं CTE

DECLARE @valor varchar(30) = "22959",
@formato varchar(30) = "000000000000000",
@text varchar(30),
@result varchar(30) = N""

SET @text = REVERSE(RIGHT(@formato + @valor, 15))

;WITH cte AS
(
SELECT 1 AS Number, SUBSTRING(@text, 1, 1) AS Num
UNION ALL
SELECT c.Number + 1,
CASE WHEN c.Number IN(3, 7, 11) THEN "." ELSE
SUBSTRING(@text, CASE WHEN c.Number > 11 THEN c.Number - 2
WHEN c.Number > 7 THEN c.Number - 1
WHEN c.Number > 3 THEN c.Number
ELSE c.Number + 1
END, 1)
END
FROM cte c
WHERE Number < LEN(@text)
)
SELECT @result += c.Num
FROM cte c
ORDER BY Number DESC

SELECT @result

डेमो देखें SQLFiddle