سؤال

أعتقد أن من الأفضل طرح هذا السؤال في شكل مثال بسيط.يتسبب الجزء التالي من SQL في حدوث خطأ "خطأ في مكتبة قاعدة البيانات: الخطورة 20049: الرسالة 4: أدى تحويل البيانات إلى تجاوز السعة" رسالة ولكن كيف؟

declare @a numeric(18,6), @b numeric(18,6), @c numeric(18,6)
select @a = 1.000000, @b = 1.000000, @c = 1.000000
select @a/(@b/@c)
go 

كيف يختلف هذا عن:

select 1.000000/(1.000000/1.000000)
go

الذي يعمل بشكل جيد؟

هل كانت مفيدة؟

المحلول

لقد واجهت نفس المشكلة في المرة الأخيرة التي حاولت فيها استخدام Sybase (منذ سنوات عديدة).انطلاقًا من عقلية SQL Server، لم أكن أدرك أن Sybase سيحاول إجبار الكسور العشرية على الخروج -- وهو ما يحدث رياضيًا يجب يفعل.:)

من دليل سايبيس:

تحدث أخطاء الفائض الحسابية عندما يكون للنوع الجديد أماكن قليلة للغاية لاستيعاب النتائج.

وإلى الأسفل:

أثناء التحويلات الضمنية إلى الأنواع الرقمية أو العشرية ، يولد فقدان المقياس خطأ في المقياس.استخدم خيار Arithabort Numeric_truncation لتحديد مدى خطورة هذا الخطأ.يقوم الإعداد الافتراضي ، Arithabort Numeric_truncation ، بإحباط العبارة التي تسبب الخطأ ولكنها تواصل معالجة عبارات أخرى في المعاملة أو الدفعة.إذا قمت بتعيين arithabort numeric_truncation ، فإن الخادم التكيفي ياقت نتائج الاستعلام ويستمر في المعالجة.

لذا على افتراض أن فقدان الدقة مقبول في السيناريو الخاص بك, ، ربما تريد ما يلي في بداية معاملتك:

SET ARITHABORT NUMERIC_TRUNCATION OFF

ثم في نهاية معاملتك:

SET ARITHABORT NUMERIC_TRUNCATION ON

هذا هو ما حل المشكلة بالنسبة لي منذ سنوات عديدة ...

نصائح أخرى

وهذا هو مجرد تكهنات، ولكن يمكن أن يكون ذلك على DBMS لا ننظر إلى قيمة ديناميكية المتغيرات الخاصة بك ولكن فقط القيم المحتملة؟ وهكذا، يمكن أن رقمية ستة عشري، مقسوما رقمية ستة عشري، يؤدي إلى رقمية اثني عشر عشري. في دوري الدرجة الحرفي، ونظم إدارة قواعد البيانات يعلم أن هناك أي تجاوز. لا يزال غير متأكد من السبب في DBMS أن تهتم، على الرغم -؟ shouldn't أن تعيد نتيجة لفرقتين ست عشرية-ما يصل الى رقمية 18 العشري

ولأنك قد أعلنت المتغيرات في المثال الأول ومن المتوقع أن يكون الإعلان نفسه (أي رقمية (18،6)) نتيجة لكنها ليست كذلك.

وأود أن أقول أن أول واحد يعمل في SQL2005 على الرغم من (عاد 1.000000 [نفس النوع أعلنت])، في حين عاد ثانية واحدة (+1.00000000000000000000000 [A إعلان مختلف الكلي]).

ولا علاقة مباشرة، ولكن ربما يمكن إنقاذ شخص بعض الوقت مع أخطاء تجاوز الحسابية باستخدام سايبيس (12.5.0.3).

ولقد وضع بعض القيم الافتراضية في جدول مؤقت الذي كنت أنوي تحديث في وقت لاحق، وتعثر على خطأ تجاوز الحسابي.

declare @a numeric(6,3)

select 0.000 as thenumber into #test --indirect declare

select @a = ( select thenumber + 100 from #test )

update #test set thenumber = @a

select * from #test

ويبين خطأ:

Arithmetic overflow during implicit conversion of NUMERIC value '100.000' to a NUMERIC field .

ما في رأسي يجب أن تعمل، ولكن لا كما لم أعلن "thenumber" العمود (أو أعلن بشكل غير مباشر كما عشري (4،3)). لذلك سيكون لديك ليعلن بشكل غير مباشر على عمود جدول مؤقت مع حجم ودقة إلى التنسيق الذي تريده، كما في حالتي كان 000.000.

select 000.000 as thenumber into #test --this solved it

ونأمل أن ينقذ شخص بعض الوقت:)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top