এই কোয়েরিটি কেন একটি FROM ধারা অনুপস্থিত, ত্রুটিযুক্ত নয়?


9

সুতরাং আমাদের একটি subquery একটি টাইপ আছে সঙ্গে একটি প্রশ্ন আছে। এটি FROM ধারাটি অনুপস্থিত। কিন্তু আপনি যখন এটি চালান, এটি ত্রুটি আউট না! কেন !?


SELECT

    1
   ,r.id
   ,'0D4133BE-C1B5-4141-AFAD-B171A2CCCE56'
   ,GETDATE()
   ,1
   ,'Y'
   ,'N'
   ,oldItem.can_view
   ,oldItem.can_update

FROM Role r

JOIN RoleObject oldReport
    ON r.customer_id = oldReport.customer_id

JOIN RoleItem oldItem
    ON oldReport.id = oldItem.role_object_id
        AND r.id = oldItem.role_id

WHERE r.id NOT IN (SELECT
        role_id
    WHERE role_object_id = '0D4133BE-C1B5-4141-AFAD-B171A2CCCE56')

AND oldReport.id = '169BA22F-1614-4EBA-AF45-18E333C54C6C'

উত্তর:


21

এই বিবৃতি আইনী (অন্য কথায়, কোনও FROMপ্রয়োজন নেই):

SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;

কৌশলটি হ'ল আপনি যখন কোনও কলামের নামটি প্রবর্তন করেন যা পরিষ্কারভাবে বিদ্যমান থাকতে পারে না। সুতরাং এগুলি ব্যর্থ:

SELECT name WHERE 1 = 1;

SELECT x = 1 WHERE id > 0;

Msg 207, স্তর 16, রাজ্য 1
অবৈধ কলামের নাম 'নাম'।
Msg 207, স্তর 16, রাজ্য 1
অবৈধ কলামের নাম 'আইডি'।

কিন্তু যখন অবৈধ কলামটি সাবকিউরির মতো কিছুতে প্রবর্তিত হয়, এসকিউএল সার্ভার যখন সাবকোরির অভ্যন্তরীণ ক্ষেত্রের মধ্যে এই কলামটি খুঁজে না পায় তখন কী করে, বাইরের স্কোপের সাথে সংযুক্ত থাকে এবং উপকণাকে সেই বাহ্যিক ক্ষেত্রের সাথে সম্পর্কিত করে তোলে। এটি সমস্ত সারি ফিরিয়ে দেবে, উদাহরণস্বরূপ:

SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);

কারণ এটি মূলত বলছে:

SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
              ^^^^^^^^^^^                       -----------
                   |                                 |
                   -----------------------------------    */

এমনকি WHEREসাবকিউরিতে আপনার একটি ধারাও প্রয়োজন নেই:

SELECT * FROM sys.columns WHERE name IN (SELECT name);

আপনি দেখতে পাচ্ছেন যে এটি সত্যই বাইরের স্কোপযুক্ত টেবিলটির দিকে তাকিয়ে আছে কারণ এটি:

SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');

অনেক কম সারি (আমার সিস্টেমে 11) ফেরায়।

এটি স্কোপিং সম্পর্কে মান মেনে চলা জড়িত। আপনার দুটি # টেম্প টেবিল থাকলে আপনি একই জিনিস দেখতে পাবেন:

CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);

SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);

একথাও ঠিক যে, এই, ডান ত্রুটি উচিত, কোন যেহেতু fooমধ্যে #bar? নাঃ। যা হয় তা এসকিউএল সার্ভার বলে, "ওহ, আমি fooএখানে একটি খুঁজে পাইনি , আপনি অবশ্যই অন্যটিকে বোঝাতে চেয়েছিলেন।"

এছাড়াও, সাধারণভাবে, আমি এড়ানো হবে NOT INNOT EXISTSকিছু পরিস্থিতিতে আরও দক্ষ হওয়ার সম্ভাবনা রয়েছে, তবে আরও বড় কথা, টার্গেট কলামটি হওয়ার সম্ভাবনা থাকলে এর আচরণ পরিবর্তন হয় না NULLআরও তথ্যের জন্য এই পোস্টটি দেখুন


স্ট্যাক ওভারফ্লোতে আমি একটি প্রশ্ন জিজ্ঞাসা করেছি যার উত্তরটি মূলত এর সমান (যদিও আপনার আরও বিশদ রয়েছে)। টেবিলের অংশ নয় এমন একটি কলাম (বাম-হাতের ক্রিয়াকলাপ হিসাবে) কেন উল্লেখ করা হচ্ছে যা এক্সআইএসটিএস অপারেটরের ত্রুটি নয়?
২২7777

2

আমি এটি একটি সরল উদাহরণ দিয়ে 2016 সালে পুনরুত্পাদন করেছি:

declare @t1 table (c1 int, c2 int, c3 int)
insert into @t1 values (1,2,3), (2,3,4), (3,4,5)

select * from @t1
where
    c1 not in 
    (select c2 where c3 = 3)

এটি প্রদর্শিত হয় যে c2 এবং c3 প্রতিটি সারির জন্য মূল্যায়ন করা হয়।


1

এসকিউএল সার্ভারে সিলেক্ট সিনট্যাক্সের FROM বিভাগের প্রয়োজন হয় না। যদি আপনি FROM বাদ দেন তবে নির্বাচন করুন বিবৃতিটি "ডামি" টেবিল ব্যবহার করবে যার একটি সারি রয়েছে এবং কোনও কলাম নেই। সুতরাং

select 'x' as c where ...

এক্সপ্রেশনটি সত্য হলে এবং একথা সারণীতে মিথ্যা হলে কোনও সারি ফিরে আসবে।


আপনি যদি কিছু বলেন select cএবং cকোনও বাহ্যিক বস্তুর অস্তিত্ব না রাখেন তবে এটি কাজ করে না। সে ব্যাপারে আমি সম্মত FROMপ্রয়োজন নেই, কিন্তু যখন আপনি স্পষ্টভাবে একটি কলাম যে নাম এখানে খেলার মধ্যে বলবিজ্ঞান করে একটি বাইরের সুযোগ থাকবেই স্পষ্টভাবে একটি ডামি টেবিল চেয়ে ভিন্ন, এবং যদি আপনি একটি কলাম যে না জন্য একটি ধ্রুবক প্রদান করবেন না বিদ্যমান, আপনি একটি রানটাইম ত্রুটি পাবেন, সুতরাং সেখানে কোনও ডামি টেবিল নেই। ডামি টেবিল অন্যান্য পরিস্থিতিতে খেলতে আসতে পারে, কিন্তু রেফারেন্সটি সাব-কোয়েরি / উত্সযুক্ত টেবিলে থাকা অবস্থায় নয়।
অ্যারন বারট্র্যান্ড

আপনার উদাহরণে এটি একটি সম্পর্কিত সম্পর্কিত সাব-সিলেক্ট, ভূমিকা_id এবং ভূমিকা_object_id বাইরের নির্বাচনের একটি সারণীর সাথে সম্পর্কিত।
পাইওটার

ডান, তবে বলা SELECT 'x' AS cওপির তুলনায় সম্পূর্ণ ভিন্ন দৃশ্য, যিনি সবেমাত্র বলেছিলেন SELECT cএকটি subquery / উত্সযুক্ত টেবিল।
অ্যারন বারট্র্যান্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.