2009-10-06 11 views
13

मैं एक Django डीबी प्रतिकृति एप्लिकेशन सामान्यीकरण की प्रक्रिया में हूँ और यह कथन का उपयोग करती:एसक्यूएल में LIMIT कथन कितना सार्वभौमिक है?

SELECT %s FROM %s LIMIT 1 

1 पंक्ति लाए जाने और क्षेत्रों का वर्णन करने के अजगर DBAPI उपयोग करने के लिए है, यह ओरेकल और MySQL लेकिन साथ ठीक काम करता है , एलआईटी कथन कैसे क्रॉस प्लेटफार्म है?

+0

ओरेकल के किन संस्करणों में है कि काम करता है चुनें? –

+0

ओरेकल 9आई @ अल्फासेवर, मेरी गलती, बस कोशिश की, काम नहीं करता है :( –

उत्तर

10

http://en.wikipedia.org/wiki/Select_(SQL)#Result_limits चुनिंदा कमांड के सभी प्रमुख रूपों को सूचीबद्ध करता है।

मुझे विश्वास है कि ऐसा करने का सबसे अच्छा तरीका आपके SELECT कथन से पहले SET ROWCOUNT कमांड का उपयोग करना है।

तो, आप के लिए:

SET ROWCOUNT 1 
SELECT %s FROM %s 
2

यह एमएसएसक्यूएल पर काम नहीं करता है (जो इसके बजाय SELECT TOP 10 * FROM Blah का उपयोग करता है)। इससे डीबी बाजार का एक महत्वपूर्ण हिस्सा निकलता है। मैं दूसरों के बारे में निश्चित नहीं हूँ।

इसके अलावा, यह संभव है, हालांकि बहुत कम संभावना है कि आपका डीबी एपीआई आपके लिए इसका अनुवाद करेगा।

2

LIMIT में 1992 मानक के रूप में ANSI SQL मानक का हिस्सा नहीं है; मेरे पास हाथ में किसी भी बाद के मानक की एक प्रति नहीं है। मानक के साथ विक्रेताओं का अनुपालन सर्वोत्तम समय पर बहुत अस्पष्ट है। इसके लायक होने के लिए, "LIMIT" को एक आरक्षित शब्द के रूप में सूचीबद्ध किया गया है (जिसका अर्थ है कि इसे कानूनी रूप से पहचानकर्ता के रूप में उपयोग नहीं किया जा सकता है, जहां भी यह कार्यान्वयन में कोई कीवर्ड नहीं है)।

12

LIMIT सार्वभौमिक से बहुत दूर है - प्रमुख आरडीबीएमएस से बाहर, यह बहुत अधिक MySQL और PostgreSQL तक सीमित है। Here एमएसएसएलएल, ओरेकल और डीबी 2, साथ ही साथ एएनएसआई एसक्यूएल सहित कई अन्य कार्यान्वयनों में यह कैसे किया जाता है इसका एक विस्तृत विश्लेषण है।

6

यह बिल्कुल सार्वभौमिक नहीं है। असल में मुझे आश्चर्य है कि यह ओरेकल में आपके लिए काम कर रहा है; यह उपस्थित होने के लिए इस्तेमाल नहीं किया गया था। आम तौर पर ओरेकल उपयोगकर्ता ROWNUM के लिए जाते हैं।

प्रत्येक डेटाबेस में पंक्ति संख्या से परिणाम सीमित करने के लिए अपना स्वयं का वाक्यविन्यास होता है। एएनएसआई मानक एसक्यूएल भी हैं:

  1. FETCH FIRST। डीबी/2 से व्युत्पन्न और केवल SQL: 2008 में मानक बनाया गया, बहुत छोटा डीबीएमएस समर्थन। ऑफ़सेट का उपयोग नहीं कर सकता।

  2. विंडोिंग फ़ंक्शन SELECT ..., ROW_NUMBER() OVER (ORDER BY some_ordering) AS rn WHERE rn BETWEEN n AND m ... ORDER BY some_ordering। यह एसक्यूएल: 2003 से है और इसमें नए डीबीएमएस में कुछ (पैची, कभी-कभी धीमी) समर्थन है। यह पंक्ति संख्या पर ऑफ़सेट या किसी अन्य तुलना फ़ंक्शन का उपयोग कर सकता है, लेकिन इसमें अजीब रूप से बदसूरत होने की कमी है।

उकताहट आप अगर तुम पार डीबीएमएस पृष्ठांकन समर्थन चाहते हैं से निपटने के लिए होगा की Here's a good overview

+0

+1 LIMIT व्यक्त करने के लिए क्रॉस-प्लेटफार्म तरीकों पर वास्तव में एक अच्छा लिंक के लिए +1। – ash108

20

LIMIT मुक्त स्रोत डेटाबेस की एक किस्म के साथ काफी लोकप्रिय हो गया है, लेकिन दुर्भाग्य से, तथ्य यह है कि OFFSET पृष्ठांकन, के रूप में देर से SQL:2008 में के रूप में मानकीकृत किया गया है उन सब से कम से कम मानकीकृत एसक्यूएल सुविधा के बारे में की गई है।

तब तक, jOOQ user manual page on the LIMIT clause दिखाता है कि कैसे विभिन्न बराबर बयान प्रत्येक एसक्यूएल बोली में गठित किया जा सकता:

-- MySQL, H2, HSQLDB, Postgres, and SQLite 
SELECT * FROM BOOK LIMIT 1 OFFSET 2 

-- CUBRID supports a MySQL variant of the LIMIT .. OFFSET clause 
SELECT * FROM BOOK LIMIT 2, 1 

-- Derby, SQL Server 2012, Oracle 12c, SQL:2008 standard 
-- Some need a mandatory ORDER BY clause prior to OFFSET 
SELECT * FROM BOOK [ ORDER BY ... ] OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY 

-- Ingres 
SELECT * FROM BOOK OFFSET 2 FETCH FIRST 1 ROWS ONLY 

-- Firebird 
SELECT * FROM BOOK ROWS 2 TO 3 

-- Sybase SQL Anywhere 
SELECT TOP 1 ROWS START AT 3 * FROM BOOK 

-- DB2 (without OFFSET) 
SELECT * FROM BOOK FETCH FIRST 1 ROWS ONLY 

-- Sybase ASE, SQL Server 2008 (without OFFSET) 
SELECT TOP 1 * FROM BOOK 

अब, इन सब सुंदर सीधी-सपाट, सही थे? यहाँ बुरा हिस्सा आता है, उन्हें अनुकरण करने के लिए आपके पास:

-- DB2 (with OFFSET), SQL Server 2008 (with OFFSET), 
SELECT * FROM (
    SELECT BOOK.*, 
    ROW_NUMBER() OVER (ORDER BY ID ASC) AS RN 
    FROM BOOK 
) AS X 
WHERE RN > 2 
AND RN <= 3 

-- DB2 (with OFFSET), SQL Server 2008 (with OFFSET) 
-- When the original query uses DISTINCT! 
SELECT * FROM (
    SELECT DISTINCT BOOK.ID, BOOK.TITLE 
    DENSE_RANK() OVER (ORDER BY ID ASC, TITLE ASC) AS RN 
    FROM BOOK 
) AS X 
WHERE RN > 2 
AND RN <= 3 

-- Oracle 11g and less 
SELECT * 
FROM (
    SELECT b.*, ROWNUM RN 
    FROM (
    SELECT * 
    FROM BOOK 
    ORDER BY ID ASC 
) b 
    WHERE ROWNUM <= 3 
) 
WHERE RN > 2 

Read about the ROW_NUMBER() vs. DENSE_RANK() rationale here

अपने जहर ;-)

+0

SQL सर्वर में, OFFSET और FETCH NEXT का उपयोग करने के लिए उपयोग की आवश्यकता है क्लॉज द्वारा ऑर्डर। – BoltBait

+0

@ बोल्टबेट: आप सही हैं, मैं इसे भूल रहा हूं। धन्यवाद! –

+0

तो ये बयान सभी तत्वों को छोड़ देते हैं और एक वापस लौटते हैं, है ना? "ऑफसेट के बिना" बयान के अप्रिय अपवाद के साथ। –

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