SQL Server String หรือข้อมูลไบนารีจะถูกตัดทอน


149

ฉันเกี่ยวข้องกับโครงการโยกย้ายข้อมูล ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อฉันพยายามแทรกข้อมูลจากตารางหนึ่งไปยังอีกตารางหนึ่ง (SQL Server 2005):

ข่าวสารเกี่ยวกับ 8152 ระดับ 16 สถานะ 13
สตริง1 หรือข้อมูลไบนารีจะถูกตัดทอน

คอลัมน์แหล่งข้อมูลตรงกับประเภทข้อมูลและอยู่ในคำจำกัดความความยาวของคอลัมน์ตารางปลายทางดังนั้นฉันจึงสูญเสียสิ่งที่อาจทำให้เกิดข้อผิดพลาดนี้


คุณต้องการโพสต์รหัสและข้อมูลเกี่ยวกับแต่ละตารางหรือไม่
Kevin Mansel

ตารางมีขนาดค่อนข้างใหญ่ดังนั้นฉันจะโพสต์เฉพาะบางส่วนของคำจำกัดความตารางที่เกี่ยวข้องและรหัส - เป็นที่ยอมรับหรือไม่
Jim Evans

คำจำกัดความของตารางและรหัสจะดีมาก
IAmTimCorey

1
ครั้งล่าสุดที่ฉันมีปัญหานี้เกิดขึ้นกับทริกเกอร์ทริกเกอร์กำลังแทรกข้อมูลในตารางตรวจสอบ มูลค่าการตรวจสอบทริกเกอร์เช่นกัน
Sachin Vishwakarma

คำตอบ:


185

คุณจะต้องโพสต์คำจำกัดความของตารางสำหรับต้นทางและปลายทางตารางสำหรับเราที่จะคิดออกว่าปัญหานี้เป็นปัญหา แต่บรรทัดล่างคือว่าหนึ่งในคอลัมน์ของคุณในตารางแหล่งที่มีขนาดใหญ่กว่าคอลัมน์ปลายทางของคุณ อาจเป็นได้ว่าคุณกำลังเปลี่ยนรูปแบบในแบบที่คุณไม่ได้รับรู้ โมเดลฐานข้อมูลที่คุณกำลังย้ายจากนั้นมีความสำคัญในการหานั้นเช่นกัน


1
ตามความคิดเห็นของฉันข้างต้น - กำลังจะมาเร็ว ๆ นี้:
Jim Evans

3
ฉันประสบปัญหาเดียวกันและต้องเปรียบเทียบประเภทคอลัมน์และขนาดทั้งหมดของทั้งสองตารางเพื่อแก้ไขปัญหา
Aziz Shaikh

1
หลังจากผ่านไปแล้ว exeecise ของการรวบรวมคำจำกัดความของตารางบางส่วนและจากนั้นรับรหัส sproc ของฉันคอลัมน์ที่กระทำผิดกระโดดออกมาที่ฉันเหมือนสายฟ้าฟาด ... ขอบคุณทุกท่านที่เข้ามา
จิมอีแวนส์

ฉันไม่สามารถบอกคุณได้ว่าฉันทำสิ่งเดียวกันกี่ครั้งแล้ว ดีใจที่คุณสามารถแก้ปัญหาของคุณได้
IAmTimCorey

ฉันทำเครื่องหมายแรกคุณตอบเป็นคำตอบเพราะมันเป็นสิ่งที่ทำให้ผมที่จะหาคำตอบ :)
จิมอีแวนส์

86

ดังที่คนอื่นพูดไปแล้วหนึ่งในคอลัมน์ข้อมูลของคุณในตารางแหล่งข้อมูลนั้นใหญ่กว่าคอลัมน์ปลายทางของคุณ

ทางออกที่ง่ายคือปิดการเตือนและอนุญาตให้มีการตัดทอน ดังนั้นหากคุณได้รับข้อผิดพลาดนี้ แต่คุณแน่ใจว่าเป็นที่ยอมรับสำหรับข้อมูลในฐานข้อมูล / ตารางเก่าของคุณที่จะถูกตัดทอน (ตัดเป็นขนาด) คุณสามารถทำสิ่งต่อไปนี้ได้

SET ANSI_WARNINGS  OFF;
-- Your insert TSQL here.
SET ANSI_WARNINGS ON;

อย่าลืมเปิดคำเตือนอีกครั้งในภายหลัง ฉันหวังว่านี่จะช่วยได้.


1
คุณช่วยฉันทำงานหลายชั่วโมง! รับขอบคุณทั้งหมดของฉัน!
Urasquirrel

เช่นเดียวกันที่นี่ บางครั้งฉันต้องเก็บข้อมูลลงในตารางจากเว็บเซอร์วิสที่มีการกำหนดประเภทข้อมูลเป็น "สตริง" เท่านั้น ฉันไม่สามารถทำให้ ทุกอย่าง Varchar (MAX) ...
ห้วน

61

ปัญหาค่อนข้างง่าย: คอลัมน์อย่างน้อยหนึ่งคอลัมน์ในคิวรีต้นทางมีข้อมูลที่เกินความยาวของคอลัมน์ปลายทาง วิธีแก้ปัญหาอย่างง่ายคือการสืบค้นแหล่งข้อมูลของคุณและดำเนินการMax(Len( source col ))ในแต่ละคอลัมน์ กล่าวคือ

Select Max(Len(TextCol1))
    , Max(Len(TextCol2))
    , Max(Len(TextCol3))
    , ...
From ...

จากนั้นเปรียบเทียบความยาวเหล่านั้นกับความยาวประเภทข้อมูลในตารางปลายทางของคุณ อย่างน้อยหนึ่งเกินความยาวคอลัมน์ปลายทาง

หากคุณมั่นใจอย่างยิ่งว่านี่ไม่ควรเป็นอย่างนั้นและไม่สนใจว่าไม่ใช่ในกรณีนั้นโซลูชันอื่นก็คือบังคับให้คอลัมน์แบบสอบถามแหล่งข้อมูลบังคับให้มีความยาวปลายทาง (ซึ่งจะตัดทอนข้อมูลใด ๆ ที่ยาวเกินไป):

Select Cast(TextCol1 As varchar(...))
    , Cast(TextCol2 As varchar(...))
    , Cast(TextCol3 As varchar(...))
    , ...
From ...

กระบวนการรายวันของฉันเริ่มต้นด้วยข้อผิดพลาดนี้ ข้อมูลที่ฉันแทรกนั้นสั้นพอที่จะใส่ได้และฉันก็มีแถวอื่น ๆ (ในตารางที่ฉันดึงมา) ด้วยสตริงขนาดใหญ่ที่ไม่เคยใส่เพราะตัวกรองของฉัน อาจเป็นดัชนีที่ถูกสร้างใหม่หรือสถิติถูกอัปเดต แต่ผีในเครื่องตัดสินใจวันหนึ่งว่ามันไม่ชอบแผนแบบสอบถามอีกต่อไปเพราะเอาลงเส้นทางที่ข้อมูล (กว้างเกินไป) "อาจ" เป็น ใส่ก่อนที่มันจะถูกกรองโดยภาคแสดงในที่ไหน - มาตรา เพื่อหลีกเลี่ยงปัญหานี้ฉันใช้ LEFT () แทน CAST - ตัวอักษรที่พิมพ์น้อยลง
MikeTeeVee

1
ขอบคุณโทมัสสิ่งนี้แปลกแม้ฉันจะไม่มีข้อมูลใด ๆ ที่ยาวเกินไปฉันยังต้องส่งมันให้มีขนาดคอลัมน์ปลายทางใหม่ทันทีที่ฉันทำ
Michelle

15

SQL Server 2019จะส่งคืนข้อความแสดงข้อผิดพลาดที่มีความหมายมากขึ้นในที่สุด

ข้อมูลไบนารีหรือสตริงจะถูกตัดทอน => การปรับปรุงข้อความแสดงข้อผิดพลาด

หากคุณมีข้อผิดพลาด (ในการผลิต) จะไม่ชัดเจนที่จะเห็นว่าคอลัมน์หรือแถวข้อผิดพลาดนี้มาจากไหนและจะค้นหาได้อย่างไร

DBCC TRACEON(460)ต้องการเปิดใช้งานการทำงานใหม่ที่คุณต้องใช้ ข้อความข้อผิดพลาดใหม่จากsys.messages:

SELECT * FROM sys.messages WHERE message_id = 2628

2628 - ข้อมูลสตริงหรือไบนารีจะถูกตัดในตาราง '%. * ls', คอลัมน์ '%. * ls' ค่าที่ตัดปลาย: '%. * ls'

สตริงหรือข้อมูลไบนารีจะถูกตัดทอน: แทนที่ข้อผิดพลาดที่น่าอับอาย 8152

ข้อความใหม่นี้ถูก backported ไปยัง SQL Server 2017 CU12 (และใน SQL Server 2016 SP2 CU ที่กำลังจะมาถึง) แต่ไม่ใช่โดยค่าเริ่มต้น คุณต้องเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับ 460 เพื่อแทนที่ ID ข้อความ 8152 ด้วย 2628 ทั้งในระดับเซสชันหรือเซิร์ฟเวอร์

โปรดทราบว่าในตอนนี้แม้ใน SQL Server 2019 CTP 2.0 จะต้องเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับเดียวกัน 460 ในรุ่นอนาคตของ SQL Server 2019 ข้อความ 2628 จะแทนที่ข้อความ 8152 โดยค่าเริ่มต้น


SQL Server 2017 CU12รองรับคุณสมบัตินี้เช่นกัน

การปรับปรุง: การแทนที่ตัวเลือกสำหรับข้อความ "สตริงหรือข้อมูลไบนารี่จะถูกตัดทอน" พร้อมข้อมูลเพิ่มเติมใน SQL Server 2017

การอัปเดต SQL Server 2017 นี้จะแนะนำข้อความเพิ่มเติมที่มีข้อมูลบริบทเพิ่มเติมต่อไปนี้

Msg 2628, Level 16, State 6, Procedure ProcedureName, Line Linenumber
String or binary data would be truncated in table '%.*ls', column '%.*ls'.
Truncated value: '%.*ls'.

ID ข้อความใหม่คือ 2628 ข้อความนี้แทนที่ข้อความ 8152 ในเอาต์พุตข้อผิดพลาดใด ๆ หากเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับ 460

db <> การสาธิตซอ


เปลี่ยนฐานข้อมูลกำหนดค่าขอบเขตแล้ว

VERBOSE_TRUNCATION_WARNINGS = {ON | ปิด}

ใช้กับ: SQL Server (เริ่มต้นด้วย SQL Server 2019 (15.x)) และ Azure SQL Database

ช่วยให้คุณเปิดใช้งานหรือปิดใช้งานสตริงใหม่หรือข้อมูลไบนารีจะถูกตัดทอนข้อผิดพลาด SQL Server 2019 (15.x) แนะนำข้อความแสดงข้อผิดพลาดใหม่ที่เฉพาะเจาะจงมากขึ้น (2628) สำหรับสถานการณ์นี้:

String or binary data would be truncated in table '%.*ls', column'%.*ls'. Truncated value: '%.*ls'.

เมื่อตั้งค่าเป็น ON ภายใต้ระดับความเข้ากันได้ของฐานข้อมูล 150 ข้อผิดพลาดของการตัดจะเพิ่มข้อความแสดงข้อผิดพลาดใหม่ 2628 เพื่อให้บริบทเพิ่มเติมและทำให้กระบวนการแก้ไขปัญหาง่ายขึ้น

เมื่อตั้งค่าเป็นปิดภายใต้ระดับความเข้ากันได้ของฐานข้อมูล 150 ข้อผิดพลาดของการตัดจะเพิ่มข้อความแสดงข้อผิดพลาดก่อนหน้า 8152

สำหรับความเข้ากันได้ของฐานข้อมูลระดับ 140 หรือต่ำกว่าข้อความแสดงข้อผิดพลาด 2628 ยังคงเป็นข้อความแสดงข้อผิดพลาดการเลือกใช้ที่ต้องเปิดใช้งานการตั้งค่าสถานะการสืบค้นกลับ 460 และการกำหนดค่าขอบเขตฐานข้อมูลนี้ไม่มีผล


1
ตอนนี้มีให้ใช้งานสำหรับ SQL Azure แล้วด้วย: azure.microsoft.com/en-gb/updates/ …
Ian Kemp

7

อีกหนึ่งเหตุผลที่เป็นไปได้สำหรับเรื่องนี้คือถ้าคุณมีการตั้งค่าเริ่มต้นสำหรับคอลัมน์ที่เกินความยาวของคอลัมน์ ดูเหมือนว่าใครบางคนอ้วนนิ้วมือของคอลัมน์ที่มีความยาว 5 แต่ค่าเริ่มต้นเกินความยาวของ 5 นี้ผลักฉันถั่วขณะที่ฉันพยายามที่จะเข้าใจว่าทำไมมันไม่ทำงานในการแทรกใด ๆ แม้ว่าฉันจะแทรก คอลัมน์เดียวที่มีจำนวนเต็ม 1 เนื่องจากค่าเริ่มต้นในตาราง schema นั้นมีการละเมิดค่าเริ่มต้นมันทำให้มันยุ่งเหยิงขึ้นหมด - ซึ่งฉันเดาว่าจะนำเราไปสู่บทเรียนที่เรียนรู้ - หลีกเลี่ยงการมีตารางที่มีค่าเริ่มต้นในสคีมา :)


1
ฉันไม่คิดว่าการหลีกเลี่ยงค่าเริ่มต้นเป็นวิธีแก้ปัญหาที่ดี ค่าเริ่มต้นมีประโยชน์มาก ฉันจะไม่แก้ไขฐานข้อมูล "ปัญหา" ที่เกิดจากความผิดพลาดโดยการเอาค่าเริ่มต้น ...
จาค็อบ H

3

สำหรับผู้อื่นให้ตรวจสอบขั้นตอนการจัดเก็บของคุณด้วย ในกรณีของฉันในขั้นตอนการจัดเก็บของCustomSearchฉันฉันตั้งใจประกาศความยาวไม่เพียงพอสำหรับคอลัมน์ของฉันดังนั้นเมื่อฉันป้อนข้อมูลขนาดใหญ่ฉันได้รับข้อผิดพลาดนั้นแม้ว่าฉันจะมีความยาวขนาดใหญ่ในฐานข้อมูลของฉัน ฉันเพิ่งเปลี่ยนความยาวของคอลัมน์ในการค้นหาที่กำหนดเองข้อผิดพลาดจะหายไป นี่เป็นเพียงการเตือนความจำ ขอบคุณ


นี่คือสิ่งที่เกิดขึ้นกับฉัน ตารางแหล่งที่มา / เป้าหมายตรงกันดี แต่ proc ที่เก็บไว้มี #table กำหนดด้วยความยาวที่สั้นกว่าและล้มเหลวที่นั่น ขอบคุณ!
Joy Walker

3

นี่อาจเป็นข้อผิดพลาดที่ท้าทาย นี่คือบันทึกบางส่วนที่นำมาจากhttps://connect.microsoft.com/SQLServer/feedback/details/339410/ค้นหาความคิดเห็นของ AmirCharania

ฉันได้ปรับคำตอบที่ AmirCharania ให้ไว้สำหรับข้อมูลที่เลือกลงในตารางจริงแทนที่จะเป็นการชั่วคราว ก่อนเลือกชุดข้อมูลของคุณลงในตารางการพัฒนาแล้วเรียกใช้ต่อไปนี้:

WITH CTE_Dev
AS (
    SELECT C.column_id
        ,ColumnName = C.NAME
        ,C.max_length
        ,C.user_type_id
        ,C.precision
        ,C.scale
        ,DataTypeName = T.NAME
    FROM sys.columns C
    INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
    WHERE OBJECT_ID = OBJECT_ID('YOUR TARGET TABLE NAME HERE, WITH SCHEMA')
    )
    ,CTE_Temp
AS (
    SELECT C.column_id
        ,ColumnName = C.NAME
        ,C.max_length
        ,C.user_type_id
        ,C.precision
        ,C.scale
        ,DataTypeName = T.NAME
    FROM sys.columns C
    INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
    WHERE OBJECT_ID = OBJECT_ID('YOUR TEMP TABLE NAME HERE, WITH SCHEMA')
    )
SELECT *
FROM CTE_Dev D
FULL OUTER JOIN CTE_Temp T ON D.ColumnName = T.ColumnName
WHERE ISNULL(D.max_length, 0) < ISNULL(T.max_length, 999)

ดูเหมือนว่า MS จะปิดเว็บไซต์เชื่อมต่อ ลิงก์ใหม่สำหรับปัญหานี้คือ: feedback.azure.com/forums/908035-sql-server/suggestions/… ... ยังคงทำเครื่องหมายว่าไม่ได้วางแผน ฉันคิดว่าความคิดเห็นที่คุณอ้างถึงถูกตัดทอน (แดกดัน) เมื่อการโยกย้ายเกิดขึ้น
SWalters - Reinstate Monica

ที่น่าสนใจปัญหาถูกเปิดอีกครั้งภายใต้ชื่อที่แตกต่างกันเล็กน้อย: feedback.azure.com/forums/908035-sql-server/suggestions/ ...... และได้รับการระบุว่าเป็น "กำลังตรวจสอบ" ดังนั้นจึงยังมีความหวัง
SWalters - Reinstate Monica

3

นี่คือคำตอบที่แตกต่างกันเล็กน้อย ชื่อและความยาวคอลัมน์ของคุณอาจตรงกันทั้งหมด แต่บางทีคุณอาจระบุคอลัมน์ในลำดับที่ไม่ถูกต้องในคำสั่ง SELECT ของคุณ สมมติว่า tableX และ tableY มีคอลัมน์ที่มีชื่อเหมือนกัน แต่เรียงลำดับต่างกัน


2

ฉันเจอปัญหานี้วันนี้และในการค้นหาคำตอบสำหรับข้อความแสดงข้อผิดพลาดที่ให้ข้อมูลน้อยที่สุดฉันพบลิงค์นี้ด้วย:

https://connect.microsoft.com/SQLServer/feedback/details/339410/please-fix-the-string-or-binary-data-would-be-truncated-message-to-give-the-column-name

ดังนั้นดูเหมือนว่าไมโครซอฟท์จะไม่มีแผนที่จะขยายข้อความแสดงข้อผิดพลาดเร็ว ๆ นี้

ดังนั้นฉันจึงหันไปใช้วิธีอื่น

ฉันคัดลอกข้อผิดพลาดไปยัง excel:

(1 แถวได้รับผลกระทบ)

(1 แถวได้รับผลกระทบ)

(รับผลกระทบ 1 แถว) ข่าวสารเกี่ยวกับ 8152, ระดับ 16, สถานะ 14, บรรทัดที่ 13 สตริงหรือข้อมูลไบนารีจะถูกตัดทอน คำสั่งถูกยกเลิก

(1 แถวได้รับผลกระทบ)

นับจำนวนแถวใน excel ได้ใกล้กับตัวนับระเบียนที่ทำให้เกิดปัญหา ... ปรับรหัสส่งออกของฉันเพื่อพิมพ์ SQL ใกล้กับมัน ... จากนั้นก็วิ่งแทรก 5 - 10 sql รอบปัญหา sql และ จัดการเพื่อระบุปัญหาหนึ่งดูสตริงที่ยาวเกินไปเพิ่มขนาดของคอลัมน์นั้นและจากนั้นนำเข้าไฟล์ขนาดใหญ่ก็ไม่มีปัญหา

บิตของการแฮ็กและวิธีแก้ปัญหา แต่เมื่อคุณเหลือทางเลือกน้อยมากคุณจะทำสิ่งที่คุณทำได้


2

ใช่ฉันกำลังเผชิญกับปัญหาเหล่านี้เช่นกัน

REMARKS VARCHAR(500)
to
REMARKS VARCHAR(1000)

ที่นี่ฉันเปลี่ยน REMARKS ยื่นความยาวจาก 500 เป็น 1,000


2

ฉันจะเพิ่มสาเหตุอื่นที่เป็นไปได้ของข้อผิดพลาดนี้เพียงเพราะไม่มีใครพูดถึงมันและอาจช่วยคนในอนาคต (เนื่องจาก OP พบคำตอบของเขา) หากตารางที่คุณกำลังแทรกมีทริกเกอร์อาจเป็นทริกเกอร์กำลังสร้างข้อผิดพลาด ฉันเคยเห็นสิ่งนี้เกิดขึ้นเมื่อคำจำกัดความเขตข้อมูลตารางถูกเปลี่ยน แต่ตารางการตรวจสอบไม่ได้


2

ใช่ - "ไพน์ลงในหม้อครึ่งไพน์จะไม่ไป" ฉันไม่ได้โชคดีมาก (ด้วยเหตุผลใดก็ตาม) ด้วย SP ต่าง ๆ ที่ผู้คนแนะนำ แต่ตราบใดที่ตารางทั้งสองอยู่ในฐานข้อมูลเดียวกัน (หรือคุณสามารถนำพวกเขาไปยังฐานข้อมูลเดียวกัน) คุณสามารถใช้ INFORMATION_SCHEMA คอลัมน์เพื่อค้นหาฟิลด์ errant ดังนั้น:

select c1.table_name,c1.COLUMN_NAME,c1.DATA_TYPE,c1.CHARACTER_MAXIMUM_LENGTH,c2.table_name,c2.COLUMN_NAME, c2.DATA_TYPE,c2.CHARACTER_MAXIMUM_LENGTH
from [INFORMATION_SCHEMA].[COLUMNS] c1
left join [INFORMATION_SCHEMA].[COLUMNS] c2 on 
c1.COLUMN_NAME=c2.COLUMN_NAME
where c1.TABLE_NAME='MyTable1'
and c2.TABLE_NAME='MyTable2'
--and c1.DATA_TYPE<>c2.DATA_TYPE
--and c1.CHARACTER_MAXIMUM_LENGTH <> c2.CHARACTER_MAXIMUM_LENGTH
order by c1.COLUMN_NAME

สิ่งนี้จะช่วยให้คุณเลื่อนขึ้นและลงเปรียบเทียบความยาวของสนามในขณะที่คุณไป ส่วนความเห็นช่วยให้คุณเห็น (ครั้งเดียว uncommented ชัด) ถ้ามีชนิดข้อมูลไม่ตรงกันหรือแสดงเฉพาะที่แตกต่างกันในความยาวสนาม - เพราะฉันขี้เกียจเกินกว่าที่จะเลื่อน - เพิ่งทราบว่าสิ่งทั้งหมดนั้นถูกบอกกล่าวกับแหล่งที่มา ชื่อคอลัมน์ที่ตรงกับเป้าหมาย


ฉันกำลังจะเขียนบางอย่างเช่นนี้ แต่คุณทำให้มันง่าย มีประโยชน์มากและทำงานเหมือนจับใจ ฉันสามารถใช้มันเพื่อเปรียบเทียบตารางที่มี 90+ คอลัมน์และสองรายการนั้นกระโดดออกมาทันที ขอบคุณ!
Joy Walker

1

ฉันใช้สตริงที่ว่างเปล่า '' ในการสร้างตารางจากนั้นได้รับข้อผิดพลาด 'ข่าวสารเกี่ยวกับ 8152 สตริงหรือข้อมูลไบนารี่จะถูกตัดทอน' ในการอัปเดตครั้งต่อไป สิ่งนี้เกิดขึ้นเนื่องจากค่าการอัพเดทที่มี 6 ตัวอักษรและใหญ่กว่าความหมายของคอลัมน์ที่คาดไว้ ฉันใช้ "SPACE" เพื่อหลีกเลี่ยงสิ่งนี้เพราะฉันรู้ว่าฉันจะอัปเดตเป็นกลุ่มหลังจากการสร้างข้อมูลเริ่มต้นนั่นคือคอลัมน์จะไม่ว่างเปล่าเป็นเวลานาน

ถ้ำขนาดใหญ่ที่นี่: นี่ไม่ใช่วิธีการแก้ปัญหาที่ลื่นไหลโดยเฉพาะ แต่มีประโยชน์ในกรณีที่คุณดึงชุดข้อมูลเช่นกันสำหรับการร้องขอข่าวกรองแบบครั้งเดียวที่คุณกำลังสร้างตารางสำหรับการทำเหมืองข้อมูลโดยใช้การประมวลผล / การตีความจำนวนมาก การจัดเก็บก่อนและหลังผลลัพธ์เพื่อการเปรียบเทียบ / การขุดในภายหลัง นี่เป็นเหตุการณ์ที่เกิดขึ้นบ่อยในสายงานของฉัน

คุณสามารถเติมข้อมูลโดยใช้คำหลัก SPACE เช่น

    select 
           Table1.[column1]
          ,Table1.[column2]
          ,SPACE(10) as column_name
    into table_you_are_creating
    from Table1
    where ...

การอัปเดตครั้งต่อไปเป็น "column_name" ที่มีอักขระ 10 ตัวหรือน้อยกว่า (ใช้แทนได้) จะได้รับอนุญาตโดยไม่ทำให้เกิดข้อผิดพลาดที่ถูกตัดทอน อีกครั้งฉันจะใช้สิ่งนี้ในสถานการณ์ที่คล้ายกับที่อธิบายไว้ในข้อแม้ของฉัน


1

ฉันได้สร้างโพรซีเดอร์ที่เก็บไว้ซึ่งวิเคราะห์ตารางต้นฉบับหรือคิวรีที่มีคุณสมบัติหลายอย่างต่อคอลัมน์ซึ่งความยาวต่ำสุด (min_len) และความยาวสูงสุด (max_len)

CREATE PROCEDURE [dbo].[sp_analysetable] (
  @tableName varchar(8000),
  @deep bit = 0
) AS

/*
sp_analysetable 'company'
sp_analysetable 'select * from company where name is not null'
*/

DECLARE @intErrorCode INT, @errorMSG VARCHAR(500), @tmpQ NVARCHAR(2000), @column_name VARCHAR(50), @isQuery bit
SET @intErrorCode=0

IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
  DROP TABLE ##tmpTableToAnalyse
END
IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
  DROP TABLE ##tmpColumns
END

if CHARINDEX('from', @tableName)>0
  set @isQuery=1

IF @intErrorCode=0 BEGIN
  if @isQuery=1 begin
    --set @tableName = 'USE '+@db+';'+replace(@tableName, 'from', 'into ##tmpTableToAnalyse from')
    --replace only first occurance. Now multiple froms may exists, but first from will be replaced with into .. from
    set @tableName=Stuff(@tableName, CharIndex('from', @tableName), Len('from'), 'into ##tmpTableToAnalyse from')
    exec(@tableName)
    IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NULL BEGIN
      set @intErrorCode=1
      SET @errorMSG='Error generating temporary table from query.'
    end
    else begin
      set @tableName='##tmpTableToAnalyse'
    end
  end
end

IF @intErrorCode=0 BEGIN
  SET @tmpQ='USE '+DB_NAME()+';'+CHAR(13)+CHAR(10)+'
  select
    c.column_name as [column],
    cast(sp.value as varchar(1000)) as description,
    tc_fk.constraint_type,
    kcu_pk.table_name as fk_table,
    kcu_pk.column_name as fk_column,
    c.ordinal_position as pos,
    c.column_default as [default],
    c.is_nullable as [null],
    c.data_type,
    c.character_maximum_length as length,
    c.numeric_precision as [precision],
    c.numeric_precision_radix as radix,
    cast(null as bit) as [is_unique],
    cast(null as int) as min_len,
    cast(null as int) as max_len,
    cast(null as int) as nulls,
    cast(null as int) as blanks,
    cast(null as int) as numerics,
    cast(null as int) as distincts,
    cast(null as varchar(500)) as distinct_values,
    cast(null as varchar(50)) as remarks
  into ##tmpColumns'
  if @isQuery=1 begin
    SET @tmpQ=@tmpQ+' from tempdb.information_schema.columns c, (select null as value) sp'
  end
  else begin
    SET @tmpQ=@tmpQ+'
      from information_schema.columns c
      left join sysobjects so    on so.name=c.table_name  and so.xtype=''U''
      left join syscolumns sc    on sc.name=c.column_name and sc.id  =so.id 
      left join sys.extended_properties sp on sp.minor_id = sc.colid AND sp.major_id = sc.id and sp.name=''MS_Description''  
      left join information_schema.key_column_usage kcu_fk    on kcu_fk.table_name = c.table_name     and c.column_name = kcu_fk.column_name
      left join information_schema.table_constraints tc_fk    on kcu_fk.table_name = tc_fk.table_name and kcu_fk.constraint_name = tc_fk.constraint_name
      left join information_schema.referential_constraints rc on rc.constraint_name = kcu_fk.constraint_name
      left join information_schema.table_constraints tc_pk    on rc.unique_constraint_name = tc_pk.constraint_name
      left join information_schema.key_column_usage kcu_pk    on tc_pk.constraint_name = kcu_pk.constraint_name
 '
  end
  SET @tmpQ=@tmpQ+' where c.table_name = '''+@tableName+''''

  exec(@tmpQ)
end

IF @intErrorCode=0 AND @deep = 1 BEGIN
  DECLARE
    @count_rows int,
    @count_distinct int,
    @count_nulls int,
    @count_blanks int,
    @count_numerics int,
    @min_len int,
    @max_len int,
    @distinct_values varchar(500)
  DECLARE curTmp CURSOR LOCAL FAST_FORWARD FOR
    select [column] from ##tmpColumns;
  OPEN curTmp
  FETCH NEXT FROM curTmp INTO @column_name
  WHILE @@FETCH_STATUS = 0 and @intErrorCode=0 BEGIN
    set @tmpQ = 'USE '+DB_NAME()+'; SELECT'+
      '  @count_rows=count(0), '+char(13)+char(10)+
      '  @count_distinct=count(distinct ['+@column_name+']),'+char(13)+char(10)+
      '  @count_nulls=sum(case when ['+@column_name+'] is null then 1 else 0 end),'+char(13)+char(10)+
      '  @count_blanks=sum(case when ltrim(['+@column_name+'])='''' then 1 else 0 end),'+char(13)+char(10)+
      '  @count_numerics=sum(isnumeric(['+@column_name+'])),'+char(13)+char(10)+
      '  @min_len=min(len(['+@column_name+'])),'+char(13)+char(10)+
      '  @max_len=max(len(['+@column_name+']))'+char(13)+char(10)+
      ' from ['+@tableName+']'
    exec sp_executesql @tmpQ,
                       N'@count_rows int OUTPUT,
                         @count_distinct int OUTPUT,
                         @count_nulls int OUTPUT,
                         @count_blanks int OUTPUT,
                         @count_numerics int OUTPUT,
                         @min_len int OUTPUT,
                         @max_len int OUTPUT',
                       @count_rows     OUTPUT,
                       @count_distinct OUTPUT,
                       @count_nulls    OUTPUT,
                       @count_blanks    OUTPUT,
                       @count_numerics OUTPUT,
                       @min_len        OUTPUT,
                       @max_len        OUTPUT

    IF (@count_distinct>10) BEGIN
      SET @distinct_values='Many ('+cast(@count_distinct as varchar)+')'
    END ELSE BEGIN
      set @distinct_values=null
      set @tmpQ = N'USE '+DB_NAME()+';'+
        '  select @distinct_values=COALESCE(@distinct_values+'',''+cast(['+@column_name+'] as varchar),  cast(['+@column_name+'] as varchar))'+char(13)+char(10)+
        '  from ('+char(13)+char(10)+
        '    select distinct ['+@column_name+'] from ['+@tableName+'] where ['+@column_name+'] is not null) a'+char(13)+char(10)
      exec sp_executesql @tmpQ,
                         N'@distinct_values varchar(500) OUTPUT',
                         @distinct_values        OUTPUT
    END
    UPDATE ##tmpColumns SET
      is_unique      =case when @count_rows=@count_distinct then 1 else 0 end,
      distincts      =@count_distinct,
      nulls          =@count_nulls,
      blanks         =@count_blanks,
      numerics       =@count_numerics,
      min_len        =@min_len,
      max_len        =@max_len,
      distinct_values=@distinct_values,
      remarks       =
        case when @count_rows=@count_nulls then 'all null,' else '' end+
        case when @count_rows=@count_distinct then 'unique,' else '' end+
        case when @count_distinct=0 then 'empty,' else '' end+
        case when @min_len=@max_len then 'same length,' else '' end+
        case when @count_rows=@count_numerics then 'all numeric,' else '' end
    WHERE [column]=@column_name

    FETCH NEXT FROM curTmp INTO @column_name
  END
  CLOSE curTmp DEALLOCATE curTmp
END

IF @intErrorCode=0 BEGIN
  select * from ##tmpColumns order by pos
end

IF @intErrorCode=0 BEGIN --Clean up temporary tables
  IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
    DROP TABLE ##tmpTableToAnalyse
  END
  IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
    DROP TABLE ##tmpColumns
  END
end

IF @intErrorCode<>0 BEGIN
  RAISERROR(@errorMSG, 12, 1)
END
RETURN @intErrorCode

ฉันเก็บขั้นตอนนี้ไว้ในฐานข้อมูลหลักเพื่อที่ฉันจะสามารถใช้มันในทุกฐานข้อมูลได้เช่น:

sp_analysetable 'table_name', 1
// deep=1 for doing value analyses

และผลลัพธ์คือ:

column description constraint_type fk_table fk_column pos default null data_type length precision radix is_unique min_len max_len nulls blanks numerics distincts distinct_values remarks
id_individual NULL PRIMARY KEY NULL NULL 1 NULL NO int NULL 10 10 1 1 2 0 0 70 70 Many (70) unique,all numeric,
id_brand NULL NULL NULL NULL 2 NULL NO int NULL 10 10 0 1 1 0 0 70 2 2,3 same length,all numeric, guid NULL NULL NULL NULL 3 (newid()) NO uniqueidentifier NULL NULL NULL 1 36 36 0 0 0 70 Many (70) unique,same length,
customer_id NULL NULL NULL NULL 4 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
email NULL NULL NULL NULL 5 NULL YES varchar 100 NULL NULL 0 4 36 0 0 0 31 Many (31)
mobile NULL NULL NULL NULL 6 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
initials NULL NULL NULL NULL 7 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_short NULL NULL NULL NULL 8 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_long NULL NULL NULL NULL 9 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
firstname NULL NULL NULL NULL 10 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
lastname NULL NULL NULL NULL 11 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
address NULL NULL NULL NULL 12 NULL YES varchar 100 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
pc NULL NULL NULL NULL 13 NULL YES varchar 10 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
kixcode NULL NULL NULL NULL 14 NULL YES varchar 20 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
date_created NULL NULL NULL NULL 15 (getdate()) NO datetime NULL NULL NULL 1 19 19 0 0 0 70 Many (70) unique,same length,
created_by NULL NULL NULL NULL 16 (user_name()) NO varchar 50 NULL NULL 0 13 13 0 0 0 1 loyalz-public same length,
id_location_created NULL FOREIGN KEY location id_location 17 NULL YES int NULL 10 10 0 1 1 0 0 70 2 1,2 same length,all numeric, id_individual_type NULL FOREIGN KEY individual_type id_individual_type 18 NULL YES int NULL 10 10 0 NULL NULL 70 0 0 0 NULL all null,empty,
optin NULL NULL NULL NULL 19 NULL YES int NULL 10 10 0 1 1 39 0 31 2 0,1 same length,


หมายเหตุด้านข้าง: คุณไม่ควรใช้sp_คำนำหน้าสำหรับขั้นตอนการจัดเก็บของคุณ Microsoft ได้สงวนคำนำหน้านั้นไว้สำหรับการใช้งานของตัวเอง (ดูขั้นตอนการตั้งชื่อการจัดเก็บ )และคุณเสี่ยงต่อการปะทะกันของชื่อในบางครั้งในอนาคต นอกจากนี้ยังเป็นที่ไม่ดีสำหรับการทำงานขั้นตอนการจัดเก็บของคุณ เป็นการดีที่สุดที่จะหลีกเลี่ยงsp_และใช้สิ่งอื่นเป็นคำนำหน้า - หรือไม่มีส่วนนำหน้าเลย!
marc_s

1

ฉันเขียนขั้นตอนการจัดเก็บที่มีประโยชน์เพื่อช่วยระบุและแก้ไขปัญหาการตัดข้อความ (สตริงหรือข้อมูลไบนารีจะถูกตัดทอน) เมื่อใช้คำสั่ง INSERT SELECT มันจะเปรียบเทียบช่อง CHAR, VARCHAR, NCHAR และ NVARCHAR เท่านั้นและส่งกลับเขตการประเมินผลโดยสนามในกรณีที่เป็นสาเหตุของข้อผิดพลาดที่เป็นไปได้

EXEC dbo.GetFieldStringTruncate SourceTableName, TargetTableName

ขั้นตอนการจัดเก็บนี้มุ่งเน้นไปที่ปัญหาการตัดข้อความเมื่อมีการสร้างคำสั่ง INSERT SELECT

การดำเนินการของขั้นตอนการจัดเก็บนี้ขึ้นอยู่กับผู้ใช้ก่อนหน้านี้ระบุคำสั่ง INSERT กับปัญหา จากนั้นแทรกข้อมูลต้นฉบับลงในตารางชั่วคราวทั่วโลก แนะนำให้ใช้คำสั่ง SELECT INTO

คุณต้องใช้ชื่อเดียวกันของเขตข้อมูลของตารางปลายทางในนามแฝงของแต่ละเขตข้อมูลของคำสั่ง SELECT

รหัสฟังก์ชั่น:

DECLARE @strSQL nvarchar(1000)
IF NOT EXISTS (SELECT * FROM dbo.sysobjects where id = OBJECT_ID(N'[dbo].[GetFieldStringTruncate]'))
    BEGIN
        SET @strSQL = 'CREATE PROCEDURE [dbo].[GetFieldStringTruncate] AS RETURN'
        EXEC sys.sp_executesql @strSQL
    END

GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

/*
------------------------------------------------------------------------------------------------------------------------
    Description:    
                    Syntax 
                    ---------------
                    dbo.GetFieldStringTruncate(SourceTable, TargetTable)
                    +---------------------------+-----------------------+
                    |   SourceTableName         |   VARCHAR(255)        |
                    +---------------------------+-----------------------+
                    |   TargetTableName         |   VARCHAR(255)        |
                    +---------------------------+-----------------------+

                    Arguments
                    ---------------
                    SourceTableName
                    The name of the source table. It should be a temporary table using double charp '##'. E.g. '##temp'

                    TargetTableName
                    The name of the target table. It is the table that receives the data used in the INSERT INTO stament.

                    Return Type
                    ----------------
                    Returns a table with a list of all the fields with the type defined as text and performs an evaluation indicating which field would present the problem of string truncation.

                    Remarks
                    ----------------
                    This stored procedure is oriented to the problem of text truncation when an INSERT SELECT statement is made.
                    The operation of this stored procedure depends on the user previously identifying the INSERT statement with the problem. Then inserting the source data into a global temporary table. The SELECT INTO statement is recommended.
                    You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.

                    Examples
                    ====================================================================================================

                    --A. Test basic

                        IF EXISTS (SELECT * FROM sys.objects  WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[tblDestino]') AND TYPE IN (N'U'))
                            DROP TABLE tblDestino

                        CREATE TABLE tblDestino
                        (
                            Id INT IDENTITY,
                            Field1 VARCHAR(10),
                            Field2 VARCHAR(12),
                            Field3 VARCHAR(11),
                            Field4 VARCHAR(16),
                            Field5 VARCHAR(5),
                            Field6 VARCHAR(1),
                            Field7 VARCHAR(1),
                            Field8 VARCHAR(6),
                            Field9 VARCHAR(6),
                            Field10 VARCHAR(50),
                            Field11 VARCHAR(50),
                            Field12 VARCHAR(50)
                        )

                        INSERT INTO dbo.tblDestino
                        (
                             Field1 ,
                             Field2 ,
                             Field3 ,
                             Field4 ,
                             Field5 ,
                             Field6 ,
                             Field7 ,
                             Field8 ,
                             Field9 ,
                             Field10 ,
                             Field11 ,
                             Field12
                            )
                        SELECT 
                             '123456789' , -- Field1 - varchar(10)
                             '123456789' , -- Field2 - varchar(12)
                             '123456789' , -- Field3 - varchar(11)
                             '123456789' , -- Field4 - varchar(16)
                             '123456789' , -- Field5 - varchar(5)
                             '123456789' , -- Field6 - varchar(1)
                             '123456789' , -- Field7 - varchar(1)
                             '123456789' , -- Field8 - varchar(6)
                             '123456789' , -- Field9 - varchar(6)
                             '123456789' , -- Field10 - varchar(50)
                             '123456789' , -- Field11 - varchar(50)
                             '123456789'  -- Field12 - varchar(50)
                        GO  

                    Result:
                        String or binary data would be truncated


                    *Here you get the truncation error. Then, we proceed to save the information in a global temporary table. 
                    *IMPORTANT REMINDER: You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.


                    Process:

                        IF OBJECT_ID('tempdb..##TEMP') IS NOT NULL DROP TABLE ##TEMP
                        go
                        SELECT 
                             [Field1] = '123456789' ,
                             [Field2] = '123456789' ,
                             [Field3] = '123456789' ,
                             [Field4] = '123456789' ,
                             [Field5] = '123456789' ,
                             [Field6] = '123456789' ,
                             [Field7] = '123456789' ,
                             [Field8] = '123456789' ,
                             [Field9] = '123456789' ,
                             [Field10] = '123456789' ,
                             [Field11] = '123456789' ,
                             [Field12] = '123456789'  
                        INTO ##TEMP

                    Result:
                    (1 row(s) affected)

                    Test:
                        EXEC dbo.GetFieldStringTruncate @SourceTableName = '##TEMP', @TargetTableName = 'tblDestino'

                    Result:

                        (12 row(s) affected)
                        ORIGEN Nombre Campo        ORIGEN Maximo Largo  DESTINO Nombre Campo     DESTINO Tipo de campo   Evaluación
                        -------------------------- -------------------- ------------------------ ----------------------- -------------------------
                        Field1                     9                    02 - Field1              VARCHAR(10)             
                        Field2                     9                    03 - Field2              VARCHAR(12)             
                        Field3                     9                    04 - Field3              VARCHAR(11)             
                        Field4                     9                    05 - Field4              VARCHAR(16)             
                        Field5                     9                    06 - Field5              VARCHAR(5)              possible field with error
                        Field6                     9                    07 - Field6              VARCHAR(1)              possible field with error
                        Field7                     9                    08 - Field7              VARCHAR(1)              possible field with error
                        Field8                     9                    09 - Field8              VARCHAR(6)              possible field with error
                        Field9                     9                    10 - Field9              VARCHAR(6)              possible field with error
                        Field10                    9                    11 - Field10             VARCHAR(50)             
                        Field11                    9                    12 - Field11             VARCHAR(50)             
                        Field12                    9                    13 - Field12             VARCHAR(50)             

                    ====================================================================================================

    ------------------------------------------------------------------------------------------------------------

    Responsible:    Javier Pardo 
    Date:           October 19/2018
    WB tests:       Javier Pardo 

    ------------------------------------------------------------------------------------------------------------

*/

ALTER PROCEDURE dbo.GetFieldStringTruncate
(
    @SourceTableName AS VARCHAR(255)
    , @TargetTableName AS VARCHAR(255)
)
AS
BEGIN
    BEGIN TRY

        DECLARE @colsUnpivot AS NVARCHAR(MAX),
            @colsUnpivotConverted AS NVARCHAR(MAX),
           @query  AS NVARCHAR(MAX)

        SELECT @colsUnpivot = stuff((
                    SELECT DISTINCT ',' + QUOTENAME(col.NAME)
                    FROM tempdb.sys.tables tab
                    INNER JOIN tempdb.sys.columns col
                        ON col.object_id = tab.object_id
                    INNER JOIN tempdb.sys.types typ
                        ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @SourceTableName
                    FOR XML path('')
                    ), 1, 1, '')
                ,@colsUnpivotConverted = stuff((
                    SELECT DISTINCT ',' + 'CONVERT(VARCHAR(MAX),' + QUOTENAME(col.NAME) + ') AS ' + QUOTENAME(col.NAME)
                    FROM tempdb.sys.tables tab
                    INNER JOIN tempdb.sys.columns col
                        ON col.object_id = tab.object_id
                    INNER JOIN tempdb.sys.types typ
                        ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @SourceTableName
                    FOR XML path('')
                    ), 1, 1, '')


        --/programming/11158017/column-conflicts-with-the-type-of-other-columns-in-the-unpivot-list
        IF OBJECT_ID('tempdb..##TablaConMaximos') IS NOT NULL DROP TABLE ##TablaConMaximos

        set @query 
          = 'SELECT u.d AS colname, MAX(LEN(u.data)) as [maximo_largo]
            INTO ##TablaConMaximos
            FROM 
            (
                SELECT ' + @colsUnpivotConverted + '
                FROM ' + @SourceTableName + '
            ) T
            UNPIVOT
             (
                data
                for d in ('+ @colsunpivot +')
             ) u
             GROUP BY u.d'

        PRINT @query

        exec sp_executesql @query;

        ------------------------------------------------------------------------------------------------------------
        SELECT --'Nombre de campo' = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
            --, 'Tipo de campo' = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
            [ORIGEN Nombre Campo] = tcm.colname
            , [ORIGEN Maximo Largo] = tcm.maximo_largo
            , [DESTINO Nombre Campo] = DESTINO.[Nombre de campo]
            , [DESTINO Tipo de campo] = DESTINO.[Tipo de campo]
            , [Evaluación] = CASE WHEN DESTINO.maximo_largo < tcm.maximo_largo THEN 'possible field with error' ELSE '' END
            --, * 
        FROM tempdb.sys.tables tab
            INNER JOIN tempdb.sys.columns col
                ON col.object_id = tab.object_id
            INNER JOIN tempdb.sys.types typ
                ON col.system_type_id = TYP.system_type_id
            RIGHT JOIN 
                (
                    SELECT column_id
                        , [Nombre de campo] = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
                        , [Tipo de campo] = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
                        , [maximo_largo] = col.max_length
                        , [colname] = col.name
                    FROM sys.tables tab
                        INNER JOIN sys.columns col
                            ON col.object_id = tab.object_id
                        INNER JOIN sys.types typ
                            ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @TargetTableName
                ) AS DESTINO
                    ON col.name = DESTINO.colname
            INNER JOIN ##TablaConMaximos tcm
                ON tcm.colname = DESTINO.colname

        WHERE tab.NAME = @SourceTableName
            AND typ.name LIKE '%char%'
        ORDER BY col.column_id

    END TRY
    BEGIN CATCH
        SELECT 'Internal error ocurred' AS Message
    END CATCH   

END

สำหรับตอนนี้สนับสนุนเฉพาะชนิดข้อมูลCHAR, VARCHAR, NCHAR และ NVARCHAR คุณสามารถค้นหารุ่นสุดท้ายของรหัสนี้ในลิงค์ถัดไปด้านล่างและเราช่วยเหลือซึ่งกันและกันในการปรับปรุง GetFieldStringTruncate.sql

https://gist.github.com/jotapardo/210e85338f87507742701aa9d41cc51d


1

หากคุณอยู่บน SQL Server 2016-2017: หากต้องการแก้ไขให้เปิดการตั้งค่าสถานะการสืบค้นกลับ 460

DBCC TRACEON(460, 1);
GO

และให้แน่ใจว่าคุณปิดหลังจาก:

DBCC TRACEOFF(460, 1);
GO

แหล่ง


0

สิ่งนี้สามารถเกิดขึ้นได้เมื่อคุณไม่มีสิทธิ์เพียงพอ


2
จริงๆ? ข้อผิดพลาด 'ข้อมูลสตริงหรือไบนารีจริงจะถูกตัดทอน' หรือไม่ ดูเหมือนจะเป็นข้อผิดพลาดที่แปลกมากถ้าคุณไม่มีสิทธิ์ใช้งาน มีสิทธิ์ที่จะหยุดคุณเขียนมากกว่าจำนวนข้อมูล? (ฉันสนใจเพราะฉันต้องการตรวจสอบขนาดฟิลด์โดยอัตโนมัติเมื่อฉันได้รับข้อผิดพลาดนี้ - ดังนั้นถ้ามันอาจเกิดขึ้นด้วยเหตุผลอื่นที่น่าสนใจมาก!)
Ian Grainger

0

ฉันมีปัญหาที่คล้ายกัน ฉันกำลังคัดลอกข้อมูลจากตารางหนึ่งไปยังตารางที่เหมือนกันทุกอย่างยกเว้นชื่อ

ในที่สุดฉันก็ทิ้งตารางต้นฉบับลงในตารางชั่วคราวโดยใช้คำสั่ง SELECT เข้า

SELECT *
INTO TEMP_TABLE
FROM SOURCE_TABLE;

ฉันเปรียบเทียบสคีมาของตารางต้นฉบับกับตารางชั่วคราว ผมพบว่าหนึ่งในคอลัมน์ที่เป็นเมื่อผมคาดหวังว่า varchar(4000)varchar(250)

ปรับปรุง: ปัญหา varchar (4000) สามารถอธิบายได้ที่นี่ในกรณีที่คุณสนใจ:

สำหรับ Nvarchar (สูงสุด) ฉันได้รับเพียง 4000 ตัวอักษรใน TSQL หรือไม่

หวังว่านี่จะช่วยได้


0

ข้อผิดพลาดนี้เกิดขึ้นเมื่อคอลัมน์ของตารางมีข้อ จำกัด [ความยาวส่วนใหญ่] . เช่นถ้าสคีมาฐานข้อมูลสำหรับคอลัมน์ myColumn คือ CHAR (2) จากนั้นเมื่อการโทรของคุณจากแอปพลิเคชันของคุณเพื่อใส่ค่าคุณต้องผ่านสตริงที่มีความยาวสอง

ข้อผิดพลาดโดยทั่วไปบอกว่ามัน; สตริงที่มีความยาวสามขึ้นไปไม่สอดคล้องกันเพื่อให้พอดีกับข้อจำกัดความยาวที่ระบุโดยสคีมาฐานข้อมูล นั่นเป็นสาเหตุที่ SQL Server เตือนและส่งข้อผิดพลาดการสูญเสียข้อมูล / การตัดปลาย


0

โปรดลองรหัสต่อไปนี้:

CREATE TABLE [dbo].[Department](
    [Department_name] char(10) NULL
)

INSERT INTO [dbo].[Department]([Department_name]) VALUES  ('Family Medicine')
--error will occur

 ALTER TABLE [Department] ALTER COLUMN [Department_name] char(50)

INSERT INTO [dbo].[Department]([Department_name]) VALUES  ('Family Medicine')

select * from [Department]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.