2009-02-03 17 views
6

नहीं में मैं इस तरह के संबंध मानचित्रण तालिका है:एसक्यूएल हटाएँ कहाँ

attributeid bigint
productid bigint

संबंधों कि किसी भी अधिक उपयोग नहीं किया जाता साफ करने के लिए, मैं सभी recors हटाना चाहते हैं जहां productid = एक्स और attributeid नहीं में (@includedIds), निम्न उदाहरण की तरह:

@attributetypeid bigint, 
@productid bigint, 
@includedids varchar(MAX) 


DELETE FROM reltable 
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (@includedids); 

जब एक से अधिक 1 आईडी युक्त includedids परम एसक्यूएल चल रहा है - इस तरह: 25,26 - मैं एक SqlException कह:

डेटा प्रकार वर्कर को बिगिन में परिवर्तित करने में त्रुटि।

और उस के कारण निश्चित रूप से है, कि varchar (max) परम में ...

मैं अपने नष्ट बयान कैसे निर्माण करना चाहिए यह काम करने के लिए?

उत्तर

2
SET QUOTED_IDENTIFIER ON 
    GO 
    CREATE FUNCTION [dbo].[ListToTable] (
    /* 
    FUNCTION ListToTable 
    Usage: select entry from listtotable('abc,def,ghi') order by entry desc 
    PURPOSE: Takes a comma-delimited list as a parameter and returns the values of that list into a table variable. 
    */ 
    @mylist varchar(8000) 
) 
    RETURNS @ListTable TABLE (
    seqid int not null, 
    entry varchar(255) not null) 

    AS 

    BEGIN 
     DECLARE 
      @this varchar(255), 
      @rest varchar(8000), 
      @pos int, 
      @seqid int 

     SET @this = ' ' 
     SET @seqid = 1 
     SET @rest = @mylist 
     SET @pos = PATINDEX('%,%', @rest) 
     WHILE (@pos > 0) 
     BEGIN 
      set @this=substring(@rest,1,@pos-1) 
      set @rest=substring(@rest,@pos+1,len(@rest)[email protected]) 
      INSERT INTO @ListTable (seqid,entry) VALUES (@seqid,@this) 
      SET @pos= PATINDEX('%,%', @rest) 
      SET @[email protected]+1 
     END 
     set @[email protected] 
     INSERT INTO @ListTable (seqid,entry) VALUES (@seqid,@this) 
     RETURN 
    END 

भागो अपने एसक्यूएल सर्वर में है कि स्क्रिप्ट फ़ंक्शन ListToTable बनाने के लिए डेटाबेस। अब, आप तो जैसे आपकी क्वेरी पुनर्लेखन कर सकते हैं:

@attributetypeid bigint, 
@productid bigint, 
@includedids varchar(MAX) 


DELETE FROM reltable 
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (SELECT entry FROM ListToTable(@includedids)); 

कहाँ @includedids एक अल्पविराम सीमांकित सूची है कि आप प्रदान करना है। सूचियों के साथ काम करते समय मैं हर समय इस समारोह का उपयोग करता हूं। ध्यान रखें कि यह फ़ंक्शन आपके इनपुट को जरूरी नहीं है, यह केवल अल्पविराम सीमित सूची में वर्ण डेटा ढूंढता है और प्रत्येक तत्व को रिकॉर्ड में रखता है। उम्मीद है की यह मदद करेगा।

+0

Sidenote: यह फ़ंक्शन SQL Server 2005 के लिए अनुकूलित नहीं है, जिसमें मैंने वर्चर्स आकार को SQL Server 2000 के साथ संगत होने के लिए 8000 पर कैप्चर किया है। यदि आपको MAX लंबाई की आवश्यकता है, तो बस स्क्रिप्ट में MAX के लिए 8000 खोजें/बदलें । – karlgrz

+0

एफवाईआई आप एनटीएक्सटी को एक परम के रूप में उपयोग कर सकते हैं जो एसक्यूएल 2000 के साथ पिछड़ा संगत है, देखें: http://www.sommarskog.se/arrays-in-sql-2000.html –

+0

@ sambo99: यह एक अच्छा सुझाव है। – karlgrz

1

योएल Spolsky यहाँ एक बहुत ही इसी तरह के सवाल का जवाब दे: Parameterize an SQL IN clause

तो आपको कुछ ऐसा की कोशिश कर सकते, एक varchar के रूप में अपने attributetypeid कास्ट करने के लिए सुनिश्चित करें।

1

आप एक पैरामीटर (AFAIK) के रूप में एक सूची पास नहीं कर सकते हैं।

आप एसक्यूएल पुनर्लेखन कर सकते हैं एक सबक्वेरी, कुछ इस तरह उपयोग करने के लिए:

delete from reltable 
WHERE productid = @productid AND 
attributetypeid = @attributetypeid AND 
attributeid NOT IN (select id from ... where ...); 

?

0

कि अल्पविराम सीमित सूची उपयोगकर्ता परिभाषित फ़ंक्शन को भेजी जा सकती है जो इसे एक साधारण तालिका के रूप में वापस कर देगी। तब उस तालिका को आपके आईएनएन द्वारा पूछताछ की जा सकती है। आप fn की जरूरत है मैं प्रदान कर सकते हैं .. यह के बारे में 5 साल कर दिया गया के बाद से मैं एसक्यूएल ज्यादा इस्तेमाल किया और मैं अपने मस्तिष्क के उस अनुभाग बंद धूल करना होगा ..

0

एसआरएल 2005 में तालिका में सूचियों से निपटने के लिए एरलैंड में definitive guide है, एसक्यूएल 2008 आपको table based params देता है।

एक तरफ नोट पर मैं बड़ी सूचियों के लिए पैटर्न में नहीं बचूंगा, क्योंकि यह स्केल नहीं करता है, इसके बजाय बाएं जुड़ने का उपयोग करके देखें।

+0

@ सैम्बो 99: एरलैंड का लेख एक महान पढ़ा गया था। लिंक के लिए धन्यवाद, जिसने निश्चित रूप से सुबह की मदद की :-) – karlgrz

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