আমি পোস্টগ্র্রেএসকিউএল সহ অভিনেত্রীটিতে ত্রুটির ক্ষেত্রে পূর্ণসংখ্যায় একটি স্ট্রিং কাস্ট করব এবং 0 টি থাকতে পারি?


128

PostgreSQL এ আমার একটি ভার্চর কলাম সহ একটি টেবিল রয়েছে। ডেটাটি পূর্ণসংখ্যার বলে মনে করা হয় এবং একটি ক্যোয়ারীতে আমার এটি পূর্ণসংখ্যার টাইপের প্রয়োজন। কিছু মান খালি স্ট্রিং হয়। পরবর্তী:

SELECT myfield::integer FROM mytable

উৎপাদনের ERROR: invalid input syntax for integer: ""

পোস্টগ্রাসে কাস্ট করার সময় আমি কীভাবে একটি কাস্টিকে জিজ্ঞাসা করতে পারি এবং 0 থাকতে পারি?

উত্তর:


161

আমি নিজেই একই ধরণের সমস্যা নিয়ে কুস্তি করছি, তবে কোনও ফাংশনের ওভারহেড চাইনি। আমি নীচের প্রশ্নটি নিয়ে এসেছি:

SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';

শর্টকাটগুলি এর শর্তযুক্ত পোস্টগ্র্যাগ পোস্ট করে, তাই আপনার :: পূর্ণসংখ্যার কাস্টে কোনও অ-পূর্ণসংখ্যার আঘাত পাওয়া উচিত নয়। এটি নুল মানগুলিও পরিচালনা করে (এগুলি রেজিপ্লেক্সের সাথে মেলে না)।

আপনি যদি না বাছাইয়ের পরিবর্তে শূন্যগুলি চান তবে একটি CASE বিবৃতিতে কাজ করা উচিত:

SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;

14
আমি জোরালোভাবে ম্যাথু এর পরামর্শ সঙ্গে যেতে সুপারিশ করব। এই সমাধানটিতে স্ট্রিংগুলির সাথে সমস্যা রয়েছে যা সংখ্যার মতো দেখায় তবে আপনি পূর্ণসংখ্যায় যে পরিমাণ মান রাখতে পারেন তার চেয়ে বড় bigger
পাইলিফ

4
আমি দ্বিতীয় পাইলফ এর মন্তব্য। যে সর্বাধিক মানটি ঘটতে অপেক্ষা করছে একটি বাগ waiting ত্রুটি নিক্ষেপ করার বিষয়টি হ'ল ডেটা অবৈধ হলে ত্রুটি ছুঁড়ে না দেওয়া। এই গৃহীত উত্তর এটি সমাধান করে না। ধন্যবাদ ম্যাথিউ! মহান কাজ!
শন কোভাক

3
ম্যাথিউয়ের উত্তরটি যতটা দুর্দান্ত, আমার কেবলমাত্র কিছু ডেটা পরীক্ষা করার জন্য হ্যান্ডলিংয়ের দ্রুত এবং নোংরা উপায়ের দরকার ছিল। আমি এটাও স্বীকার করি যে এসকিউএল-তে কার্যকারিতা সংজ্ঞায়িত করার জন্য আমার নিজের জ্ঞানের এখনই অভাব রয়েছে। আমি কেবল 1 এবং 5 সংখ্যার মধ্যে সংখ্যার প্রতি আগ্রহী ছিলাম, তাই আমি রেজেক্সকে পরিবর্তিত করেছি E'\\d{1,5}$'
বোবার্ট

3
হ্যাঁ, হ্যাঁ এই সমাধানটি তুলনামূলকভাবে দ্রুত এবং নোংরা, তবে আমার ক্ষেত্রে আমি জানতাম আমার কী ডেটা ছিল এবং টেবিলটি তুলনামূলকভাবে সংক্ষিপ্ত। এটি পুরো ফাংশনটি লেখার (এবং ডিবাগিং) চেয়ে অনেক সহজ। {1,5}ওভারফ্লো সম্পর্কে উদ্বিগ্ন থাকলে @ বক্টের উপরের অঙ্কগুলিতে সীমাটি সম্ভবত একটি ভাল ধারণা, তবে এটি বড় সংখ্যক মুখোশ ফেলবে , যদি আপনি কোনও টেবিলটি রূপান্তর করেন তবে সমস্যা হতে পারে। ব্যক্তিগতভাবে আমি বরং ক্যোয়ারির ত্রুটিটি সামনে রেখে জানতাম এবং জানতে পারি যে আমার "পূর্ণসংখ্যার" কিছু চতুর ( E'\\d{6,}$'নিশ্চিত করার জন্য আপনি প্রথমটিও নির্বাচন করতে পারেন)।
অ্যান্টনি ব্রিগেস

1
@ অ্যান্টনি ব্রিগস: মাইফিল্ডে "" "বা", "বা"। ", বা '-' থাকলে এটি কাজ করবে না
স্টিফান স্টিগার

100

আপনি নিজের রূপান্তর ফাংশনও তৈরি করতে পারেন , যার মধ্যে আপনি ব্যতিক্রম ব্লকগুলি ব্যবহার করতে পারেন:

CREATE OR REPLACE FUNCTION convert_to_integer(v_input text)
RETURNS INTEGER AS $$
DECLARE v_int_value INTEGER DEFAULT NULL;
BEGIN
    BEGIN
        v_int_value := v_input::INTEGER;
    EXCEPTION WHEN OTHERS THEN
        RAISE NOTICE 'Invalid integer value: "%".  Returning NULL.', v_input;
        RETURN NULL;
    END;
RETURN v_int_value;
END;
$$ LANGUAGE plpgsql;

পরীক্ষামূলক:

=# select convert_to_integer('1234');
 convert_to_integer 
--------------------
               1234
(1 row)

=# select convert_to_integer('');
NOTICE:  Invalid integer value: "".  Returning NULL.
 convert_to_integer 
--------------------

(1 row)

=# select convert_to_integer('chicken');
NOTICE:  Invalid integer value: "chicken".  Returning NULL.
 convert_to_integer 
--------------------

(1 row)

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

বিবৃতিতে থাকার সময় আপনি কীভাবে নির্দিষ্ট ক্ষেত্রগুলিতে পূর্ণসংখ্যায় স্ট্রিং কাস্ট করবেন INSERT?
এসকি

27

আমার একই ধরণের প্রয়োজন ছিল এবং এটি আমার পক্ষে ভালভাবে কাজ করার জন্য খুঁজে পেয়েছে (8.4 পোস্ট করুন):

CAST((COALESCE(myfield,'0')) AS INTEGER)

কিছু পরীক্ষার কেস প্রদর্শন করার জন্য:

db=> select CAST((COALESCE(NULL,'0')) AS INTEGER);
 int4
------
    0
(1 row)

db=> select CAST((COALESCE('','0')) AS INTEGER);
 int4
------
    0
(1 row)

db=> select CAST((COALESCE('4','0')) AS INTEGER);
 int4
------
    4
(1 row)

db=> select CAST((COALESCE('bad','0')) AS INTEGER);
ERROR:  invalid input syntax for integer: "bad"

আপনার যদি ক্ষেত্রের অ-সংখ্যাযুক্ত পাঠ্য (যেমন "100bad") থাকার সম্ভাবনাটি পরিচালনা করতে হয় তবে আপনি youালাইয়ের আগে সংখ্যাসূচক অক্ষরগুলি ছাঁটাতে regexp_replace ব্যবহার করতে পারেন।

CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)

তারপরে "বি 3 এড 5" এর মতো পাঠ্য / বর্ণের মানগুলিও সংখ্যা দেবে

db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
 regexp_replace
----------------
             35
(1 row)

"খারাপ" (কোনও অঙ্কের অক্ষর নেই) এর মতো একটি মামলা সহ সমস্ত ক্ষেত্রে 0 না দেওয়ার সমাধানের সাথে ক্রিস কগডনের উদ্বেগের সমাধান করার জন্য, আমি এই সমন্বিত বিবৃতি দিয়েছিলাম:

CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);

এটি সরল সমাধানগুলির মতোই কাজ করে, 0 দেবে ব্যতীত যখন রূপান্তর করার মানটি কেবলমাত্র অ-অঙ্কের অক্ষর যেমন "খারাপ" হয়:

db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
     coalesce
----------
        0
(1 row)

আপনার '0' দরকার কেন || ? দস্তাবেজগুলি থেকে: "কুলসেসি ফাংশনটি তার আর্গুমেন্টগুলির প্রথমটি দেয় যা শূন্য নয়" " সুতরাং আপনার মানটি যদি বাতিল হয় তবে কোলেসেস এ থেকে মুক্তি পাবেন।
আমালা

@ আমালা ট্রু সুন্দর ক্যাচ. সম্পাদনা করা হয়েছে।
gbarratt

1
সমাধান কেবল তখনই কাজ করে যদি ইনপুটটি পূর্ণসংখ্যা বা NULL হয়। প্রশ্নটি কোনও ধরণের ইনপুট রূপান্তর করতে বলছিল, এবং রূপান্তরযোগ্য না হলে 0 ব্যবহার করুন।
ক্রিস কগডন

@ ক্রিসকগডন আমি রূপান্তর করার মানটি "রূপান্তরযোগ্য নয়" হিসাবে সর্বদা শূন্য না দিয়ে আপনার উদ্বেগের সমাধানের সমাধানটিতে যুক্ত করেছি। সমাধানের এই টুইটযুক্ত সংস্করণটি 0 ফিরে আসবে যখন কোনও সংখ্যার অক্ষরযুক্ত একটি স্ট্রিং রূপান্তর করার জন্য মান হিসাবে দেওয়া হয়।
ghbarratt

22

এটি কিছুটা হ্যাক হতে পারে তবে এটি আমাদের ক্ষেত্রে কাজটি সম্পন্ন করেছে:

(0 || myfield)::integer

ব্যাখ্যা (পোস্টগ্রেস 8.4 এ পরীক্ষিত):

উল্লিখিত অভিব্যক্তিটি শূন্য স্ট্রিংগুলিতে এবং খালি স্ট্রিংগুলিতে NULLনুল-মানগুলির জন্য ফল দেয় (এই সঠিক আচরণটি আপনার ব্যবহারের ক্ষেত্রে উপযুক্ত হতে পারে বা নাও পারে)।myfield0

SELECT id, (0 || values)::integer from test_table ORDER BY id

পরীক্ষার ডেটা:

CREATE TABLE test_table
(
  id integer NOT NULL,
  description character varying,
  "values" character varying,
  CONSTRAINT id PRIMARY KEY (id)
)

-- Insert Test Data
INSERT INTO test_table VALUES (1, 'null', NULL);
INSERT INTO test_table VALUES (2, 'empty string', '');
INSERT INTO test_table VALUES (3, 'one', '1');

ক্যোয়ারী নিম্নলিখিত ফলাফল দেবে:

 ---------------------
 |1|null        |NULL|
 |2|empty string|0   |
 |3|one         |1   |
 ---------------------

যেখানে কেবল নির্বাচন values::integerকরলে ত্রুটি বার্তায় ফলাফল আসে।

আশাকরি এটা সাহায্য করবে.


3

SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable

আমি পোস্টগ্রিজএসকিউএল এর সাথে কখনও কাজ করি নি তবে আমি নির্বাচনী প্রশ্নের মধ্যে যদি বিবৃতিগুলির সঠিক বাক্য গঠনটির জন্য ম্যানুয়ালটি পরীক্ষা করেছিলাম ।


এটি এখন যেমন টেবিলের জন্য কাজ করে। আমি কিছুটা ভয় পেয়েছি যে ভবিষ্যতে এটিতে সংখ্যাসূচক মান থাকতে পারে। আমি চেষ্টা / ধরার মতো সমাধান পছন্দ করতাম তবে এটি কৌশলটি কার্যকর করে। ধন্যবাদ।
সিলভিট

হতে পারে আপনি নিয়মিত এক্সপ্রেশন postgresql.org/docs/8.4/interactive/function-matching.html ব্যবহার করতে পারেন তবে তা ব্যয়বহুল হতে পারে। উত্তরটি যদি সমাধান হয় তবে তা গ্রহণ করুন :)
জান হানিয়ে

3

@ ম্যাথু এর উত্তর ভাল। তবে এটি সহজ এবং দ্রুত হতে পারে। এবং প্রশ্নটি খালি স্ট্রিংগুলিকে ( '') রূপান্তর করতে বলে 0, তবে অন্যান্য "অবৈধ ইনপুট সিনট্যাক্স" বা "সীমার বাইরে" ইনপুট নয়:

CREATE OR REPLACE FUNCTION convert_to_int(text)
  RETURNS int AS
$func$
BEGIN
   IF $1 = '' THEN  -- special case for empty string like requested
      RETURN 0;
   ELSE
      RETURN $1::int;
   END IF;

EXCEPTION WHEN OTHERS THEN
   RETURN NULL;  -- NULL for other invalid input

END
$func$  LANGUAGE plpgsql IMMUTABLE;

এটি 0খালি স্ট্রিংয়ের NULLজন্য এবং অন্য কোনও অবৈধ ইনপুটটির জন্য ফিরে আসে ।
এটি যে কোনও ডেটা ধরণের রূপান্তরের জন্য সহজেই মানিয়ে নেওয়া যায়

একটি ব্যতিক্রম ব্লক প্রবেশ করা যথেষ্ট ব্যয়বহুল। যদি খালি স্ট্রিংগুলি সাধারণ থাকে তবে একটি ব্যতিক্রম উত্থাপনের আগে সেই কেসটি ধরা অর্থপূর্ণ।
যদি খালি স্ট্রিংগুলি খুব বিরল হয়, তবে এটি পরীক্ষা ব্যতিক্রম বিভাগে সরিয়ে দেওয়ার জন্য অর্থ প্রদান করে।


1
CREATE OR REPLACE FUNCTION parse_int(s TEXT) RETURNS INT AS $$
BEGIN
  RETURN regexp_replace(('0' || s), '[^\d]', '', 'g')::INT;
END;
$$ LANGUAGE plpgsql;

0ইনপুট স্ট্রিংয়ে কোনও অঙ্ক না থাকলে এই ফাংশনটি সর্বদা ফিরে আসবে ।

SELECT parse_int('test12_3test');

ফিরে আসবে 123


আপনি কি রেজেক্স বনাম স্ট্রিং ফাংশনটির জন্য কোনও পারফরম্যান্স পরীক্ষা করেছেন? এছাড়াও, কিভাবে এই হ্যান্ডেল নালস? এটি প্রত্যাশিত 0 বা NULL ফিরে আসবে? ধন্যবাদ!
ভোলআরন

1

আমি নীচের কোডটি সহজ এবং কার্যকারী পেয়েছি। আসল উত্তরটি এখানে https://www.postgresql.org/message-id/371F1510.F86C876B@sferacarta.com

prova=> create table test(t text, i integer);
CREATE

prova=> insert into test values('123',123);
INSERT 64579 1

prova=> select cast(i as text),cast(t as int)from test;
text|int4
----+----
123| 123
(1 row)

আশা করি এটা সাহায্য করবে


1

জমা দেওয়া কিছু ক্ষেত্রে সাহায্য করতে পারে, আপনি কোন আকারের আকার সীমাবদ্ধ করতে পারেন।

SELECT CAST(SUBSTRING('X12312333333333', '([\d]{1,9})') AS integer);

0

যদি ডেটাটি পূর্ণসংখ্যার হিসাবে বিবেচিত হয় এবং আপনার কেবলমাত্র পূর্ণসংখ্যার হিসাবে সেই মানগুলি প্রয়োজন হয় তবে আপনি কেন পুরো মাইলটি যান এবং কলামটিকে একটি পূর্ণসংখ্যা কলামে রূপান্তর করবেন না?

তারপরে আপনি অবৈধ মানগুলির এই রূপান্তরটি ঠিক একবারে জিরোতে করতে পারেন, সিস্টেমের পয়েন্টে যেখানে ডাটা সারণীতে sertedোকানো হয়।

উপরের রূপান্তরটির সাথে আপনি পোস্টগ্রিজকে সেই টেবিলের জন্য প্রতিটি ক্যোয়ারির প্রতিটি একক সারির জন্য সেই মানগুলিকে বারবার রূপান্তর করতে বাধ্য করছেন - আপনি যদি এই টেবিলের এই কলামটির বিরুদ্ধে অনেকগুলি প্রশ্ন করেন তবে এটি গুরুত্ব সহকারে কর্মক্ষমতা হ্রাস করতে পারে।


নীতিগতভাবে আপনি ঠিক বলেছেন, তবে এই বিশেষ দৃশ্যে আমাকে একটি অ্যাপ্লিকেশনে একটি একক ধীর ক্যোয়ারী অনুকূল করতে হবে। আমি জানি না যে কোড কীভাবে ডেটা ইনপুট পরিচালনা করে। আমি এটি স্পর্শ করতে চাই না। এখনও অবধি আমার পুনর্লিখিত ক্যোয়ারীটি কাজ করে তবে আমি এটি অপ্রত্যাশিত ক্ষেত্রে না ভাঙতে চাই। অ্যাপ্লিকেশনটিকে নতুন করে আর্কিটেকিং করা কোনও বিকল্প নয়, এমনকি যদি এটি সবচেয়ে বুদ্ধিমান জিনিস মনে হয়।
সিলভিট

0

নিম্নলিখিত ফাংশন করে

  • error_resultcastালাইযোগ্য ফলাফলের জন্য একটি ডিফল্ট মান ( ) ব্যবহার করুন যেমনabc বা999999999999999999999999999999999999999999
  • রাখে nullহিসাবেnull
  • ইনপুটটিতে ফাঁকা স্থান এবং অন্যান্য সাদা স্থানকে ছাঁটাই করে
  • বৈধ হিসাবে গণ্য করা মানগুলির bigintsসাথে তুলনা করা lower_boundহয় যেমন কেবলমাত্র ইতিবাচক মান প্রয়োগ করা
CREATE OR REPLACE FUNCTION cast_to_bigint(text) 
RETURNS BIGINT AS $$
DECLARE big_int_value BIGINT DEFAULT NULL;
DECLARE error_result  BIGINT DEFAULT -1;
DECLARE lower_bound   BIGINT DEFAULT 0;
BEGIN
    BEGIN
        big_int_value := CASE WHEN $1 IS NOT NULL THEN GREATEST(TRIM($1)::BIGINT, lower_bound) END;
    EXCEPTION WHEN OTHERS THEN
        big_int_value := error_result;
    END;
RETURN big_int_value;
END;

-1

আমারও একই চাহিদা রয়েছে তবে এটি জেপিএ 2.0 এবং হাইবারনেট 5.0.2 এর সাথে কাজ করে:

SELECT p FROM MatchProfile p WHERE CONCAT(p.id, '') = :keyword

বিস্ময়কর কাজ করে। আমি মনে করি এটিও লাইকের সাথে কাজ করে।


-3

এটির কাজটিও করা উচিত তবে এটি এসকিউএল জুড়ে এবং পোস্টগ্রাগ নির্দিষ্ট নয়।

select avg(cast(mynumber as numeric)) from my table
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.