यह अनूठे मुख्य बाधा उल्लंघन के साथ क्यों विफल हो जाता है?


12

मैं एक "आकस्मिक" डीबीए हूं, इस समस्या से अपेक्षाकृत अनुभवहीन और चकित हूं।

MS SQL सर्वर 2012 चला रहा है। समस्या इस अद्यतन कथन के साथ है:

UPDATE dbo.tAccts SET
       Ticket               = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
FROM dbo.vReclaimable
WHERE OHR_EmpStatus <> 'A'

जो tAccts तालिका में केवल उन पंक्तियों को अद्यतन करना चाहिए जो vReclaimable दृश्य द्वारा वापस आ जाती हैं।

VReclaimable दृश्य tAccts तालिका पर आधारित है और tAccts में पंक्तियों का एक सबसेट लौटाता है।

जब मैं इसे चलाता हूं, तो यह एक अद्वितीय कुंजी त्रुटि के साथ विफल हो जाता है:

(0 row(s) affected)
Msg 2627, Level 14, State 1, Line 67
Violation of UNIQUE KEY constraint 'UQ__tAccounts_DNIS.Method.Destination.Phones'. Cannot insert duplicate key in object 'dbo.tAccts'. The duplicate key value is (68497, smtp, r00417819@mail.ad.ge.com, 800-905-8793, none).
The statement has been terminated.

उचित रूप से, tAccts तालिका में एक विशिष्ट कुंजी बाधा होती है:

CONSTRAINT [UQ__tAccounts_DNIS.Method.Destination.Phones] UNIQUE NONCLUSTERED 
(
                [DNIS] ASC,[Method] ASC,[Destination] ASC,[Phone_TF] ASC,[Phone_Local] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 

लेकिन यहाँ अजीब बात है। अगर मैं इन दो प्रश्नों को चलाता हूं:

select 'tAccts table', dnis, method, destination, phone_tf, phone_local from tAccts where dnis=68497
select 'vReclaimable view', dnis, method, destination, phone_tf, phone_local, daysidle from vReclaimable where dnis=68497

पहली दो पंक्तियाँ लौटाती हैं (अपेक्षानुसार):

(No column name)     dnis   method destination   phone_tf      phone_local
tAccts table  68497  ftp    ftp://faxuser@ap1plm02cige/appliances    800-905-8793  none
tAccts table  68497  unc    \\\\for4as01applge\\cfs_portfolio\\cfs_faxdocs  800-905-8793  none

और दूसरा रिटर्न 0 पंक्तियाँ (जैसा कि अपेक्षित है)।

यदि "VReclaimable WHERE OHR_EmpStatus <> 'A' से 0 पंक्तियाँ मिलती हैं, तो UPDATE उस पंक्ति को अद्यतन करने का प्रयास क्यों कर रहा है जहाँ DNIS = 68497 है?

(मुझे आशा है कि मैंने इसे पर्याप्त रूप से वर्णित किया है। मुझे लग रहा है कि मुझे कुछ स्पष्ट याद आ रहा है)

USE [TEST-GEAFax_arley_NEW]
GO

/****** Object:  Table [dbo].[tAccts]    Script Date: 12/9/2015 1:39:41 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tAccts](
    [Ticket] [varchar](30) NOT NULL,
    [Method] [varchar](15) NOT NULL,
    [AcctOwner] [varchar](15) NOT NULL,
    [DisplayName] [varchar](75) NOT NULL,
    [Destination] [varchar](75) NOT NULL,
    [DNIS] [varchar](20) NOT NULL,
    [DNIS2] [varchar](20) NULL,
    [Phone_TF] [varchar](30) NOT NULL,
    [Phone_Local] [varchar](30) NOT NULL,
    [Phone_PBX] [varchar](255) NOT NULL,
    [UpdatedBy] [varchar](50) NOT NULL,
    [UpdatedOn] [date] NOT NULL,
    [FaxNotes] [varchar](255) NULL,
    [TelcomNotes] [varchar](255) NULL,
    [AcctID] [int] IDENTITY(0,1) NOT NULL,
 CONSTRAINT [PK__tAccounts_AcctID] PRIMARY KEY CLUSTERED 
(
    [AcctID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [UQ__tAccounts_DNIS.Method.Destination.Phones] UNIQUE NONCLUSTERED 
(
    [DNIS] ASC,
    [Method] ASC,
    [Destination] ASC,
    [Phone_TF] ASC,
    [Phone_Local] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

---------------------------------------------------------------------------------

USE [TEST-GEAFax_arley_NEW]
GO

/****** Object:  View [dbo].[vReclaimable]    Script Date: 12/9/2015 1:39:57 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


/***********************************************************************
* Written By    : N. Arley Dealey (200018252
* Written On    :
* Updated By    :
* Updated On    :
* Description   : Returns data from tAccts, vRxAl, vWLT_AllGE
* Notes         :
***********************************************************************/
CREATE VIEW [dbo].[vReclaimable] AS
SELECT
        a.Ticket
        , a.Method
        , a.AcctOwner
        , a.DisplayName
        , a.Destination
        , a.DNIS
        , a.DNIS2
        , a.Phone_TF
        , a.Phone_Local
        , a.Phone_PBX
        , a.UpdatedBy
        , a.UpdatedOn
        , a.FaxNotes
        , a.TelcomNotes
        , a.AcctID
        , COUNT(jt.JobID) AS 'FaxesRcvd'
        , CAST(MIN(jt.TimeStamp_UTC) AS DATE) AS 'FirstRcvd'
        , CAST(MAX(jt.TimeStamp_UTC) AS DATE) AS 'LastRcvd'
        , DATEDIFF(dd, MAX(jt.TimeStamp_UTC), GETDATE()) AS 'DaysIdle'
        , o.OHR_EmpSSO
        , o.OHR_EmpStatus
        , o.OHR_EmpName
        , o.OHR_EmpTitle
        , o.OHR_BizIndustryGroup
        , o.OHR_BizSegment
        , o.OHR_BizUnit
        , o.OHR_BizDept
        , o.OHR_BizDomain
FROM
    dbo.tAccts AS a
    LEFT OUTER JOIN dbo.tAccts_Retain AS r ON (a.AcctID = r.AcctID)
    LEFT OUTER JOIN dbo.vWLT_AllGE AS o ON (a.AcctOwner = o.OHR_EmpSSO)
    LEFT OUTER JOIN dbo.vRxAll AS jt ON (a.DNIS = jt.DNIS)
    WHERE ( 1                                               -- place holder, has no effect
            AND r.RetainID IS NULL                          -- out of scope: in Retain table
            AND a.Method = 'smtp'                           -- out of scope: ftp, unc, cifs, printers
            AND a.Phone_Local NOT LIKE '216-%'              -- out of scope: NELA numbers
            AND a.AcctOwner <> 'r00417819'                  -- out of scope: reclaimed numbers
            AND a.AcctOwner <> 'r00336832'                  -- out of scope: never assigned numbers
            AND a.AcctOwner <> 'r00971729'                  -- out of scope: invalid numbers
            AND a.Destination NOT LIKE 'g%@mail.ad.ge.com'  -- out of scope: distribution lists
            AND a.Destination NOT LIKE 'r%@mail.ad.ge.com'  -- out of scope: shared mailboxes
        )
    GROUP BY
        a.DNIS
        -- remaining columns are just for syntax reasons
        , a.Ticket, a.Method, a.AcctOwner, a.DisplayName, a.Destination, a.DNIS2, a.Phone_TF, a.Phone_Local, a.Phone_PBX, a.UpdatedBy, a.UpdatedOn, a.FaxNotes, a.TelcomNotes, a.AcctID
        , o.OHR_EmpSSO, o.OHR_EmpStatus, o.OHR_EmpName, o.OHR_EmpTitle
        , o.OHR_BizIndustryGroup, o.OHR_BizSegment, o.OHR_BizUnit, o.OHR_BizDept, o.OHR_BizDomain

GO

हमें CREATE VIEWबयान दिखाओ ।
ypercube y

और OHR_EmpStatusतालिका का एक स्तंभ है, दृश्य या दोनों?
ypercube y

1
मैं बस अपने प्रश्न की त्वरित और उत्कृष्ट प्रतिक्रिया की मात्रा पर आधारित हूं। जैसा कि मैंने कहा, यह शायद कुछ स्पष्ट है जिसे मैंने अनदेखा किया है या गलत समझा है, लेकिन मुझे नहीं लगता कि यह इसलिए है क्योंकि मैंने क्रॉस-जॉइन किया है। मुझे tAccts तालिका और vReclaimable दृश्य के लिए परिभाषाएँ पोस्ट करनी चाहिए थीं। मैं अब तक पोस्ट किए गए सभी उत्तरों की समीक्षा करूंगा, और अगर मुझे लगता है कि वे अभी भी लक्ष्य पर सही नहीं हैं, तो मैं उन परिभाषाओं को प्रश्न में जोड़ दूंगा। इस बीच, सभी ने जवाब दिया है जो एक बड़ा धन्यवाद।
अरलीड

TAccts और vReclaimable दोनों के लिए क्रिएट स्टेटमेंट्स को जोड़ते हुए, जैसा कि ypercube द्वारा अनुरोध किया गया है
ArleyD

जवाबों:


18

यह उकसाता है कि UPDATEबयान क्या करता है। यह पूरी तरह से स्पष्ट नहीं है लेकिन आपका कथन इस के बराबर है:

UPDATE upd SET
         Ticket             = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
FROM 
    dbo.tAccts AS upd 
  CROSS JOIN
    dbo.vReclaimable AS v
WHERE OHR_EmpStatus <> 'A' ;

के बाद से वहाँ का कोई जिक्र नहीं है dbo.tAcctsमें मेज FROMऔर कोई शामिल होने या एक जहां मेज और दृश्य के बीच हालत है, यह परिणाम में CROSSशामिल होने और अद्यतन करने के लिए एक प्रयास तालिका की सभी पंक्तियों (सिर्फ देखने से नहीं और), और शायद कई साथ ही समय!


आप के साथ एक शर्त (या जहां) जोड़ सकते हैं:

UPDATE upd SET
         Ticket             = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
FROM 
    dbo.tAccts AS upd 
  JOIN
    dbo.vReclaimable AS v
      ON v.PK = upd.PK              -- whatever the PK column is
WHERE OHR_EmpStatus <> 'A' ;

या (अपने संस्करण का उपयोग करके):

UPDATE dbo.tAccts SET
       Ticket               = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
FROM dbo.vReclaimable
WHERE OHR_EmpStatus <> 'A'
  AND vReclaimable.PK = tAccts.PK ;

वैकल्पिक रूप से, आप (शायद) बस दृश्य को अपडेट कर सकते हैं। यह काम करने के लिए, दृश्य को "अपडेट करने योग्य दृश्य" के बारे में सीमाओं के अनुरूप होना चाहिए । : MSDN प्रलेखीकरण पर प्रासंगिक पैराग्राफ देखें CREATE VIEW, updatable दृश्य :

UPDATE dbo.vReclaimable SET
       Ticket               = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)

WHERE OHR_EmpStatus <> 'A' ;

2

ऐसा लगता है कि आपकी अपडेट क्वेरी में तालिकाओं के बीच कोई जुड़ाव नहीं है।

UPDATE dbo.tAccts SET
       Ticket               = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
FROM dbo.vReclaimable
WHERE OHR_EmpStatus <> 'A'

यहाँ तालिकाओं के बीच पंक्तियों का मिलान करने के लिए कुछ होना चाहिए जैसे कि tAccts.id = vReclaimable.id


2

इसे लगाने का दूसरा तरीका:

मुद्दा आपका विश्वास है कि बयान "tAccts तालिका में केवल पंक्तियों को अद्यतन करना चाहिए जो vReclaimable दृश्य द्वारा लौटाए जाते हैं"।

ऐसी बात नहीं है। यह सभी पंक्तियों tAccts(तालिका के ठीक बाद में उल्लिखित UPDATE) से अद्यतन करता है जो मैच OHR_EmpStatus <> 'A'(स्थिति में ) से मेल खाता है WHERE। यह ऐसा करने से डेटा का उपयोग vReclaimableकर सकता है (लेकिन आप इसके लिए कोई संदर्भ नहीं बनाते हैं)।

यदि आप इसे उन पंक्तियों तक सीमित करना चाहते हैं vReclaimable, जो प्रस्तुत किए गए अन्य विकल्पों के अतिरिक्त हैं, तो आप एक उपश्रेणी का उपयोग कर सकते हैं:

UPDATE dbo.tAccts SET
       Ticket               = 'ARP.ExGE'
       , Method             = 'smtp'
       , AcctOwner          = 'r00417819'
       , DisplayName = '~AppLight HBSFax-Inactive'
       , Destination = 'r00417819@mail.ad.ge.com'
       , UpdatedBy          = SYSTEM_USER
       , UpdatedOn          = CAST(GetDate() AS DATE)
WHERE OHR_EmpStatus <> 'A' AND tAccts.key IN (SELECT key FROM vReclaimable)

0

यदि नीचे की क्वेरी एक पंक्ति से अधिक लौटती है:

select 'tAccts table', dnis, method, destination, phone_tf, phone_local 
from tAccts
where OHR_EmpStatus <> 'A'

फिर आप एक ही मान के साथ कई पंक्तियों को अपडेट करने का प्रयास कर रहे हैं, इसलिए अद्वितीय बाधा का उल्लंघन कर रहे हैं।


: भी लायक में इस की तलाश में हो सकता है stackoverflow.com/questions/2648445/...
infiniteLoop

0

एक और विकल्प है: आप की जरूरत नहीं है

Dbo.vReclaimable से

क्योंकि आप अपने अपडेट स्टेटमेंट में इस तालिका से किसी भी मूल्य का उपयोग नहीं करते हैं।


रिकॉर्ड के लिए: इस मामले में, vReclaimableनिस्संदेह अद्यतन किए जा रहे टेबल को फ़िल्टर करने के लिए निस्संदेह इरादा था। हालांकि यह SETक्लॉज के लिए आवश्यक नहीं है , यह प्रभावी रूप से WHEREक्लॉज का हिस्सा है ।
जॉन ऑफ ऑल ट्रेड्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.