কেন আমাকে কলাম টাইপ করতে নুল কাস্ট করতে হবে?


10

আমার কাছে এমন একটি সহায়ক পেয়েছি যা আমার জন্য বাল্ক আপডেট করার জন্য কিছু কোড উত্পন্ন করে এবং এসকিউএল তৈরি করে যা দেখে মনে হয়:

(সক্রিয় এবং মূল ক্ষেত্র উভয় প্রকারের boolean)

UPDATE fields as t set "active" = new_values."active","core" = new_values."core"
FROM (values 
(true,NULL,3419),
(false,NULL,3420)
) as new_values("active","core","id") WHERE new_values.id = t.id;

তবে এটি এতে ব্যর্থ হয়:

ERROR: column "core" is of type boolean but expression is of type text

::booleanনালগুলিতে যোগ করে আমি এটি কাজ করতে পারি , তবে এটি কেবল অদ্ভুত বলে মনে হয়, কেন নুলকে ধরণের বিবেচনা করা হয় TEXT?

এছাড়াও এটি কাস্ট করা কিছুটা জটিল কারণ কোডটি কীভাবে টাইপ করা উচিত তা জানার জন্য কোডটির পুনর্নির্মাণের বেশ খানিকটা প্রয়োজন (কলাম এবং মানগুলির তালিকা বর্তমানে জেএসওন অবজেক্টের একটি সাধারণ অ্যারে থেকে স্বয়ংক্রিয়ভাবে তৈরি করা হচ্ছে) ।

কেন এটি প্রয়োজনীয় এবং এমন কি আরও একটি দুর্দান্ত সমাধান রয়েছে যার জন্য জেনারেটিং কোডের প্রয়োজন হয় না নুলের প্রকারটি জানতে?

যদি এটি প্রাসঙ্গিক হয় তবে আমি এটি করার জন্য নোড.জেএস এর উপর সিক্যুয়ালাইজ ব্যবহার করছি তবে পোস্টগ্রিস কমান্ড লাইন ক্লায়েন্টেও একই ফলাফল পাচ্ছি।

উত্তর:


16

এটি একটি আকর্ষণীয় অনুসন্ধান। সাধারণত, কোনও এনএলএল এর কোনও অনুমান করা ডেটা ধরণের নেই, আপনি এখানে দেখতে পারেন:

SELECT pg_typeof(NULL);

 pg_typeof 
───────────
 unknown

কোনও VALUESটেবিল ছবিতে এলে এটি পরিবর্তন হয়:

SELECT pg_typeof(core) FROM (
    VALUES (NULL)
) new_values (core);

 pg_typeof 
───────────
 text

এই আচরণটি উত্স কোডে https : //do ऑक्सीजन . পোস্টগ্রেসক্ল.আর.এল / পার্স__কোসর_8 c.html#l01373 তে বর্ণিত হয়েছে :

 /*
  * If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
  * then resolve as type TEXT.  This situation comes up with constructs
  * like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
  * UNION SELECT 'bar'; It might seem desirable to leave the construct's
  * output type as UNKNOWN, but that really doesn't work, because we'd
  * probably end up needing a runtime coercion from UNKNOWN to something
  * else, and we usually won't have it.  We need to coerce the unknown
  * literals while they are still literals, so a decision has to be made
  * now.
  */

(হ্যাঁ, পোস্টগ্রিজ এসকিউএল উত্স কোডটি তুলনামূলকভাবে সহজ এবং বেশিরভাগ জায়গাগুলি, দুর্দান্ত মন্তব্যে ধন্যবাদ)

উপায়, যদিও, নিম্নলিখিত হতে পারে। ধরা যাক আপনি সর্বদা VALUESএমন সারণি তৈরি করছেন যা প্রদত্ত টেবিলের সমস্ত কলামের সাথে মেলে (অন্যান্য ক্ষেত্রে নীচের দ্বিতীয় নোটটি দেখুন)। আপনার উদাহরণ থেকে, একটি ছোট কৌশল সম্ভবত সাহায্য করতে পারে:

SELECT (x).* FROM (VALUES ((TRUE, NULL, 1234)::fields)) t(x);

 active  core   id  
────────┼──────┼──────
 t             1234

এখানে আপনি টেবিলের ধরণে সজ্জিত সারি অভিব্যক্তি ব্যবহার করুন এবং তারপরে এগুলি আবার টেবিলের সাথে বের করে আনতে পারেন।

উপরের উপর ভিত্তি করে, আপনার UPDATEমত দেখতে পারে

UPDATE fields AS t set active = (x).active, core = (x).core
FROM ( VALUES
           ((true, NULL, 3419)::fields),
           ((false, NULL, 3420)::fields)
     ) AS new_values(x) WHERE (x).id = t.id;

মন্তব্য:

  • উন্নত মানব পাঠযোগ্যতার জন্য আমি দ্বিগুণ উদ্ধৃতিগুলি সরিয়েছি, তবে (কলাম) নাম উত্পন্ন করার সময় আপনি সেগুলি সহায়তা করতে পারেন।
  • আপনার যদি কলামগুলির কেবল একটি উপসেট প্রয়োজন হয় তবে আপনি এই উদ্দেশ্যে কাস্টম প্রকার তৈরি করতে পারেন । আপনার উপরের মতো একইভাবে সেগুলি ব্যবহার করুন (যেখানে আমি টেবিলের সাথে স্বয়ংক্রিয়ভাবে তৈরি টাইপটি ব্যবহার করি যা পরের সারি কাঠামোটি ধারণ করে)।

ডিবিফিডেলে কাজ করে পুরো জিনিসটি দেখুন ।


ধন্যবাদ, এটি আকর্ষণীয়, তবে আমার জন্য, উপরের কোডটি উত্পন্ন করে Cannot cast type boolean to bigint in column 1(প্রথম ক্ষেত্রের বিবৃতিটির মধ্যে :: :: এ ত্রুটি পয়েন্ট)
ক্রিস্টোফারজে

1
@ ক্রিস্টোফেরজে জবাবটি ধরে নিয়েছে যে ডাকা টেবিলটিতে বুলেটিয়ান, বুলিয়ান এবং ইন্ট / বিগিন্ট প্রকার সহ fields3 টি কলাম রয়েছে (active, core, id)। আপনার টেবিলটিতে আরও কলাম বা বিভিন্ন ধরণের রয়েছে বা কলামগুলি বিভিন্ন ক্রমে সংজ্ঞায়িত হয়েছে?
ypercubeᵀᴹ

আমি দেখছি, ধন্যবাদ, হ্যাঁ আরও কলাম এবং বিভিন্ন ক্রমে রয়েছে। ধন্যবাদ, পেয়েছি
ক্রিস্টোফার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.