2014-10-17 4 views
6

का उपयोग कर स्ट्रिंग में चार से अलग अक्षर बदलें, मेरे पास एक तालिका में NVARCHAR(10) कॉलम है। यह किसी भी प्रकार के यूनिकोड तारों को स्टोर कर सकता है।एसक्यूएल सर्वर: कोई अस्थायी तालिका

मैं प्रत्येक चार्ट को '0' से '0' से अलग करना चाहता हूं।

मान लें कि मेरे पास स्ट्रिंग 'C18 *' है। मुझे '0100000100' मिलना चाहिए।

मैं जो इस तरह मेरे कॉलम (10), का आकार 1 से अनुक्रमित शामिल एक सहायक तालिका का उपयोग कर यह करने के लिए कामयाब रहे:

CREATE TABLE HELP(Idx INT) 
INSERT INTO HELP 
    SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT  7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 

DECLARE @myStr VARCHAR(10) 
SET @myStr = 'C18*' 

SELECT STUFF((SELECT '' + CASE(B.Ch) WHEN '1' THEN '1' ELSE '0' END FROM (
    SELECT SUBSTRING(A.Val,H.Idx,1) AS Ch 
    FROM 
    (SELECT @myStr AS Val) A 
    CROSS JOIN HELP H 
)B FOR XML PATH('')),1,0,'') 

यह काम करता है, लेकिन यह एक अच्छा किया जा सकता है मार्ग? यह एक साधारण अपडेट के लिए बदसूरत लगता है, इस तथ्य को अनदेखा कर रहा है कि कॉलम का आकार समय के साथ बदल सकता है। इसे एसक्यूएल> = 2005 पर भी चलाना है।

एसक्यूएल फिडलhere

धन्यवाद!

+0

में परीक्षण किया गया है कि आप केवल एक मानक proc के साथ ऐसा कर सकते हैं या आप नेट प्रक्रिया का उपयोग कर सकते हैं? क्या ऐसा कुछ है जिसे डेटा को साफ़ करने के लिए कई बार चलाने या सिर्फ एक बार चलाने की आवश्यकता है? –

+0

@ मॉरीस रिव्स इसे दर्जनों बड़ी टेबल (10 के + पंक्तियों) के खिलाफ केवल एक बार (हमारे कुछ डेटाबेस में कुछ भ्रष्ट डेटा) चलाना है। एक साधारण कंसोल ऐप इसे हल कर लेगा, लेकिन मैंने पूछा कि एक ही स्थिति फिर से होती है + मुझे उस अस्थायी तालिका पसंद नहीं है। – darkdante

+2

एक संख्या तालिका बहुत उपयोगी है। कई लोगों को एक स्थायी तालिका के रूप में है। –

उत्तर

5

यहां एक सीटीई के साथ ऐसा करने का एक तरीका है। मेरे सिस्टम में मैं वास्तव में ctesTally दृश्य नाम के रूप में ctes है। यह तकनीक शून्य पढ़ने के साथ 10,000 पंक्ति दृश्य उत्पन्न करती है। ;) पोस्ट के रूप में आपका कोड काफी अच्छी तरह से काम करता है। इस उदाहरण के लिए मैंने स्ट्रिंग को एक टेबल में ले जाया क्योंकि यह वास्तविक प्रणाली में आप काम कर रहे हैं।

declare @myStrings table(MyVal varchar(10)); 

insert @myStrings 
select 'C18*'; 

WITH 
    E1(N) AS (select 1 from 
    (
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1) union all 
     select (1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 

SELECT STUFF((SELECT '' + CASE(B.Ch) WHEN '1' THEN '1' ELSE '0' END FROM (
    SELECT SUBSTRING(A.MyVal, t.N, 1) AS Ch 
    FROM 
    @myStrings A 
    CROSS JOIN cteTally t 
    where t.N < LEN(a.MyVal) 
)B FOR XML PATH('')),1,0,'') 
+1

मुझे एससीएल 2005 के साथ काम करने के लिए थोड़ा सा सीटी संशोधित करना पड़ा। 2008+ में आप इसे मान (1), (1), (1), (1), (1), (1), (1) में बदल सकते हैं), (1), (1), (1) सभी चयनों के बजाय। : डी –

+0

मैंने अभी अपनी तकनीक के साथ अपनी संख्याओं को देखा है! धन्यवाद :) – darkdante

+0

क्या आप बिना किसी स्पष्ट आदेश के उपखंड में पंक्तियों के क्रम पर भरोसा कर सकते हैं? –

1

यदि आप पूरी तालिका को अपडेट करना चाहते हैं तो यूडीएफ उपयोगी हो सकता है।

Create FUNCTION dbo.F_MakeBinary(@Param NVarchar(max)) 
RETURNS NVarchar (max) 
AS 
BEGIN  
DECLARE @a NVarchar(max) 
Set @[email protected] 
While PATINDEX(N'%[^0-1]%', @a) > 0 
begin  
    select @a=STUFF(@a, PATINDEX(N'%[^0-1]%', @a),1,'0') 
end 
Return @a 
END 

उपयोग:

Update aTable Set aField = dbo.F_MakeBinary(aField) 
7

एक थोड़ा अलग दृष्टिकोण, एक पुनरावर्ती क्वेरी का उपयोग:

WITH cte AS 
    (SELECT v, i = 0, 
     nv = CAST('' AS NVARCHAR(10)) 
    FROM t 
    UNION ALL 
    SELECT v, i+1, 
     CAST(nv + CASE WHEN SUBSTRING(v, i+1, 1) = '1' THEN '1' ELSE '0' END 
      AS NVARCHAR(10)) 
    FROM cte 
    WHERE i+1 <= LEN(v) 
) 
SELECT v, nv 
FROM cte 
WHERE i = LEN(v) ; 

SQLFiddle

संबंधित मुद्दे