SQL सर्वर में Oracle के पंक्ति के समतुल्य


84

SQL सर्वर में Oracle के RowID के बराबर क्या है?


स्टेफ़नी: धारणा यह है कि डेटा में एक अद्वितीय कुंजी है, जो मानती है कि डेटा सामान्यीकृत है, जो कभी-कभी एक गलत धारणा है। इस प्रकार, SQL सर्वर में Oracle के RowID के बराबर क्या है।
क्रिस्टोफर महान

जवाबों:


117

ओरेकल डॉक्स से

ROWID Pseudocolumn

डेटाबेस में प्रत्येक पंक्ति के लिए, ROWID pseudocolumn पंक्ति का पता देता है। Oracle डेटाबेस पंक्ति मान में पंक्ति का पता लगाने के लिए आवश्यक जानकारी है:

  • ऑब्जेक्ट का डेटा ऑब्जेक्ट नंबर
  • डेटाफ़ाइल में डेटा ब्लॉक जिसमें पंक्ति रहती है
  • डेटा ब्लॉक में पंक्ति की स्थिति (पहली पंक्ति 0 है)
  • डेटाफ़ाइल जिसमें पंक्ति रहती है (पहली फ़ाइल 1 है)। फ़ाइल नंबर टेबलस्पेस के सापेक्ष है।

SQL सर्वर में इसके समीपतम ridतीन घटक हैं File:Page:Slot

SQL सर्वर 2008 में यह देखने के लिए अनिर्दिष्ट और असमर्थित %%physloc%%वर्चुअल कॉलम का उपयोग करना संभव है । यह binary(8)पहले चार बाइट्स में पेज आईडी के साथ एक वैल्यू देता है , फिर फाइल आईडी के लिए 2 बाइट्स, उसके बाद पेज पर स्लॉट लोकेशन के लिए 2 बाइट्स।

स्केलर फ़ंक्शन sys.fn_PhysLocFormatterया sys.fn_PhysLocCrackerटीवीएफ का उपयोग इसे अधिक पठनीय रूप में परिवर्तित करने के लिए किया जा सकता है

CREATE TABLE T(X INT);

INSERT INTO T VALUES(1),(2)

SELECT %%physloc%% AS [%%physloc%%],
       sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot]
FROM T

उदाहरण आउटपुट

+--------------------+----------------+
|    %%physloc%%     | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0)   |
| 0x2926020001000100 | (1:140841:1)   |
+--------------------+----------------+

ध्यान दें कि यह क्वेरी प्रोसेसर द्वारा लीवरेज्ड नहीं है। जबकि इसका उपयोग एक खंड में करना संभव हैWHERE

SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100 

SQL सर्वर सीधे निर्दिष्ट पंक्ति की तलाश नहीं करेगा । इसके बजाय यह एक पूर्ण तालिका स्कैन करेगा, %%physloc%%प्रत्येक पंक्ति के लिए मूल्यांकन करेगा और जो मेल खाता है (यदि कोई हो) उसे लौटा दें।

पहले से उल्लेख किए गए 2 कार्यों द्वारा किए गए प्रक्रिया को उल्टा करने के लिए और binary(8)ज्ञात फ़ाइल, पृष्ठ, स्लॉट के मूल्यों के अनुरूप मूल्य प्राप्त करें, जिसका नीचे उपयोग किया जा सकता है।

DECLARE @FileId int = 1,
        @PageId int = 338,
        @Slot   int = 3

SELECT CAST(REVERSE(CAST(@PageId AS BINARY(4))) AS BINARY(4)) +
       CAST(REVERSE(CAST(@FileId AS BINARY(2))) AS BINARY(2)) +
       CAST(REVERSE(CAST(@Slot   AS BINARY(2))) AS BINARY(2))

SQL सर्वर 2005 पर आप अनिर्दिष्ट और असमर्थित वर्चुअल कॉलम %% LockRes %% का उपयोग कर सकते हैं
हेनरिक होल्मगार्ड हॉयर

पूर्ण सही। %% LockRes%% "सही तरीका" नहीं है - केवल उपयोग करें अगर qucik और गंदे फिक्स के लिए डेटा के पुराने संस्करणों पर sql सर्वर 2008 से पहले
हेनरिक होल्मगार्ड हॉयर

11

मुझे कई स्तंभों के साथ एक बहुत बड़ी तालिका काटनी है और गति महत्वपूर्ण है। इस प्रकार मैं इस पद्धति का उपयोग करता हूं जो किसी भी तालिका के लिए काम करती है:

delete T from 
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1

9

नया ROW_NUMBER फ़ंक्शन देखें। यह इस तरह काम करता है:

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE

15
मुझे लगता है कि यह रोन्नम का रिप्लेसमेंट है न कि राउडी।
09:54

9

यदि आप अपने परिणाम सेट के बजाय तालिका के भीतर एक पंक्ति को विशिष्ट रूप से पहचानना चाहते हैं, तो आपको आईडीबीआई कॉलम की तरह कुछ का उपयोग करने की आवश्यकता है। SQL सर्वर मदद में "पहचान की संपत्ति" देखें। SQL सर्वर तालिका में प्रत्येक पंक्ति के लिए एक आईडी को स्वतः उत्पन्न नहीं करता है जैसा कि Oracle करता है, इसलिए आपको अपना स्वयं का आईडी स्तंभ बनाने की परेशानी में जाना होगा और स्पष्ट रूप से इसे अपनी क्वेरी में लाना होगा।

संपादित करें: परिणाम सेट पंक्तियों की डायनामिक नंबरिंग के लिए नीचे देखें, लेकिन यह संभवतः ओरेकल के डाउनलोड के लिए एक समान होगा और मैं उस पृष्ठ पर सभी टिप्पणियों से मान लेता हूं जो आप ऊपर सामान चाहते हैं। SQL सर्वर 2005 के लिए और बाद में आप पंक्तियों की गतिशील संख्या को प्राप्त करने के लिए नए रैंकिंग फ़ंक्शंस फ़ंक्शन का उपयोग कर सकते हैं ।

उदाहरण के लिए मैं यह एक प्रश्न पर करता हूं:

select row_number() over (order by rn_execution_date asc) as 'Row Number', rn_execution_date as 'Execution Date', count(*) as 'Count'
from td.run
where rn_execution_date >= '2009-05-19'
group by rn_execution_date
order by rn_execution_date asc

तुम्हे दूंगा:

Row Number  Execution Date           Count
----------  -----------------        -----
1          2009-05-19 00:00:00.000  280
2          2009-05-20 00:00:00.000  269
3          2009-05-21 00:00:00.000  279

डायनामिक नंबरिंग पंक्तियों पर support.microsoft.com पर एक लेख भी है ।


मुझे लगता है कि एक पहचान स्तंभ विशिष्ट रूप से एक तालिका में एक पंक्ति की पहचान करता है, लेकिन डेटाबेस में नहीं।

यह सच है, लेकिन यह उस Oracle की परिभाषा पर फिट बैठता है जिसे मैं Oracle डॉक्स में देखता हूं: "बाहरी डेटाटाइप ROWID एक डेटाबेस तालिका में एक विशेष पंक्ति को पहचानता है" ... लेकिन मैं देख रहा हूं कि आप अपने टाइपो के कारण ऐसा कह रहे हैं ऊपर। :) यह बात बताने के लिए धन्यवाद।
शियाओफू

एक पंक्ति "संख्या" एक ROWID नहीं है। ROWID में पंक्ति का भौतिक स्थान होता है जो एक अद्वितीय संख्या से कुछ अलग होता है। विशेष रूप से यह डेटाबेस में सभी तालिकाओं के बीच अद्वितीय है (कुछ अपवादों के साथ जब विशेष भंडारण तकनीकों का उपयोग किया जाता है)
a_horse_with_no_name

6

ऊपर दिए गए कई उत्तर एक विशिष्ट पंक्ति के सीधे संदर्भ की कमी के आसपास काम करेंगे , लेकिन एक तालिका में अन्य पंक्तियों में परिवर्तन होने पर काम नहीं करेंगे । यह मेरा मापदंड है जिसके लिए उत्तर तकनीकी रूप से कम हैं।

Oracle के ROWID का एक सामान्य उपयोग पंक्तियों का चयन करने के लिए (कुछ हद तक) स्थिर विधि प्रदान करना है और बाद में इसे संसाधित करने के लिए पंक्ति में लौटना है (जैसे, इसे अपडेट करना)। एक पंक्ति को खोजने की विधि (जटिल जोड़, पूर्ण-पाठ खोज, या पंक्ति-दर-पंक्ति ब्राउज़ करना और डेटा के खिलाफ प्रक्रियात्मक परीक्षण लागू करना) आसानी से या सुरक्षित रूप से अद्यतन नहीं किया जा सकता है जो अद्यतन विवरण को अर्हता प्राप्त करने के लिए उपयोग किया जाता है।

SQL सर्वर RID समान कार्यक्षमता प्रदान करने के लिए लगता है, लेकिन समान प्रदर्शन प्रदान नहीं करता है। यह एकमात्र मुद्दा है जिसे मैं देख रहा हूं, और दुर्भाग्य से एक ROWID को बनाए रखने का उद्देश्य एक बहुत बड़ी तालिका में पंक्ति को खोजने के लिए एक महंगा ऑपरेशन को दोहराने से बचना है। बहरहाल, कई मामलों के लिए प्रदर्शन स्वीकार्य है। यदि Microsoft भविष्य के रिलीज़ में ऑप्टिमाइज़र को समायोजित करता है, तो प्रदर्शन समस्या का समाधान किया जा सकता है।

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

कैविएट: यहां तक ​​कि Oracle का ROWID स्थिर नहीं होगा यदि DBA, SELECT और UPDATE के बीच, उदाहरण के लिए, डेटाबेस का पुनर्निर्माण करना था, क्योंकि यह भौतिक पंक्ति पहचानकर्ता है। तो ROWID डिवाइस का उपयोग केवल एक अच्छी तरह से स्कूप किए गए कार्य के भीतर किया जाना चाहिए।


3

यदि आप एक छोटे डेटासेट के लिए बस मूल पंक्ति क्रमांकन चाहते हैं, तो इस तरह से कुछ कैसे करें?

SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees

लेकिन यह क्विक एडेड आईडी के लिए काम करता है, जिसे कुछ दर्शक ढूंढ रहे होंगे, न कि यह जानकर कि ROWID क्या है।
ग्रीम

3

से http://vyaskn.tripod.com/programming_faq.htm#q17 :

Oracle में पंक्ति संख्या या पंक्ति आईडी का उपयोग करके तालिका की पंक्तियों तक पहुँचने के लिए एक पंक्ति है। SQL सर्वर में क्या इसके लिए कोई समकक्ष है? या SQL Server में पंक्ति संख्या के साथ आउटपुट कैसे उत्पन्न करें?

SQL सर्वर में Oracle की rownum या पंक्ति आईडी के बराबर कोई प्रत्यक्ष नहीं है। कड़े शब्दों में, एक संबंधपरक डेटाबेस में, एक तालिका के भीतर पंक्तियों का आदेश नहीं दिया जाता है और एक पंक्ति आईडी वास्तव में कोई मतलब नहीं होगा। लेकिन अगर आपको उस कार्यक्षमता की आवश्यकता है, तो निम्नलिखित तीन विकल्पों पर विचार करें:

  • IDENTITYअपनी तालिका में एक कॉलम जोड़ें ।

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

    SELECT (SELECT COUNT(i.au_id) 
            FROM pubs..authors i 
            WHERE i.au_id >= o.au_id ) AS RowID, 
           au_fname + ' ' + au_lname AS 'Author name'
    FROM          pubs..authors o
    ORDER BY      RowID
    
  • IDENTITY() फ़ंक्शन द्वारा जनरेट की गई पंक्ति id के साथ, संपूर्ण परिणाम को एक अस्थायी तालिका में संग्रहीत करने के लिए, एक अस्थायी तालिका दृष्टिकोण का उपयोग करें । एक अस्थायी तालिका बनाना महंगा होगा, खासकर जब आप बड़ी तालिकाओं के साथ काम कर रहे हों। इस दृष्टिकोण के लिए जाएं, यदि आपके पास अपनी तालिका में कोई विशिष्ट कुंजी नहीं है।


3

यदि आप तालिका में पंक्तियों को स्थायी रूप से क्रमांकित करना चाहते हैं, तो कृपया SQL सर्वर के लिए RID समाधान का उपयोग न करें। यह एक पुराने 386 पर पहुंच से भी बदतर प्रदर्शन करेगा। SQL सर्वर के लिए बस एक पहचान कॉलम बनाएं, और उस कॉलम का उपयोग एक प्राथमिक प्राथमिक कुंजी के रूप में करें। यह टेबल पर एक स्थायी, तेज इंटेगर बी-ट्री रखेगा और इससे भी महत्वपूर्ण बात यह है कि हर गैर-क्लस्टर इंडेक्स पंक्तियों का पता लगाने के लिए इसका उपयोग करेगा। यदि आप SQL सर्वर में विकसित करने का प्रयास करते हैं जैसे कि यह Oracle है तो आप एक खराब प्रदर्शन करने वाला डेटाबेस बनाएंगे। आपको इंजन के लिए अनुकूलन करने की आवश्यकता है, दिखावा नहीं है यह एक अलग इंजन है।

GUID के साथ प्राथमिक कुंजी को पॉप्युलेट करने के लिए कृपया न्यूआईडी () का उपयोग न करें, आप सम्मिलित प्रदर्शन को मार देंगे। यदि आप GUID का उपयोग करना चाहते हैं तो कॉलम डिफ़ॉल्ट के रूप में NewSequentialID () का उपयोग करें। लेकिन INT अब भी तेज होगा।

यदि दूसरी ओर, आप बस क्वेरी से उत्पन्न होने वाली पंक्तियों को संख्या देना चाहते हैं, तो क्वेरी कॉलम में से एक के रूप में रोवनम्बर ओवर () फ़ंक्शन का उपयोग करें।



1

ROWID ओरेकल टेबल पर एक छिपा हुआ कॉलम है, इसलिए, SQL सर्वर के लिए, अपना स्वयं का निर्माण करें। डिफ़ॉल्ट मान के साथ ROWID नामक एक कॉलम जोड़ें NEWID()

ऐसा कैसे करें: SQL सर्वर में मौजूदा तालिका में, डिफ़ॉल्ट मान के साथ कॉलम जोड़ें


1
यह एक टिप्पणी के अधिक नहीं है?
अनफुन कैट

1

कृपया देखें http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx SQL सर्वर में टाइमस्टैम्प डेटाइम कॉलम के समान नहीं है। यह एक डेटाबेस में एक पंक्ति को विशिष्ट रूप से पहचानने के लिए उपयोग किया जाता है, न केवल एक तालिका बल्कि संपूर्ण डेटाबेस। यह आशावादी संगोष्ठी के लिए इस्तेमाल किया जा सकता है। उदाहरण के लिए UPDATE [नौकरी] SET [नाम] = @ नाम, [XCustomData] = @ XCustomData WHERE ([मॉडिफाइड टाइमस्टैम्प] = @ Original_ModifiedTimeStamp AND [GUID] @ Original_GUID

ModifiedTimeStamp यह सुनिश्चित करता है कि आप मूल डेटा को अपडेट कर रहे हैं और पंक्ति में एक और अपडेट होने पर विफल हो जाएगा।


0

मैंने इस उदाहरण को MS SQL उदाहरण से लिया है और आप देख सकते हैं कि @ID को पूर्णांक या varchar या जो भी हो, के साथ इंटरचेंज किया जा सकता है। यह वही समाधान था जिसकी मुझे तलाश थी, इसलिए मैं इसे साझा कर रहा हूं। का आनंद लें!!

-- UPDATE statement with CTE references that are correctly matched.
DECLARE @x TABLE (ID int, Stad int, Value int, ison bit);
INSERT @x VALUES (1, 0, 10, 0), (2, 1, 20, 0), (6, 0, 40, 0), (4, 1, 50, 0), (5, 3, 60, 0), (9, 6, 20, 0), (7, 5, 10, 0), (8, 8, 220, 0);
DECLARE @Error int;
DECLARE @id int;

WITH cte AS (SELECT top 1 * FROM @x WHERE Stad=6)
UPDATE x -- cte is referenced by the alias.
SET ison=1, @id=x.ID
FROM cte AS x

SELECT *, @id as 'random' from @x
GO

0

आप नीचे दिए गए तरीकों का उपयोग करके ROWID प्राप्त कर सकते हैं:

1. इसमें ऑटो इन्क्रीमेंट फील्ड के साथ एक नया टेबल बनाएं

2. अपनी आवश्यकता के आधार पर अनुक्रम प्राप्त करने के लिए Row_Number विश्लेषणात्मक फ़ंक्शन का उपयोग करें। मैं इसे पसंद करूंगा क्योंकि यह उन स्थितियों में मदद करता है जब आप चाहते हैं कि आप एक विशिष्ट क्षेत्र या खेतों के संयोजन के आरोही या अवरोही तरीके से row_id चाहते हैं

नमूना: रो_नंबर () ओवर (साल्ट अवर द्वारा विभाग द्वारा आदेश)

ऊपर नमूना आपको प्रत्येक विभाग के उच्चतम वेतन के आधार पर अनुक्रम संख्या देगा। इसके द्वारा वैकल्पिक वैकल्पिक है और आप इसे अपनी आवश्यकताओं के अनुसार निकाल सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.