“Dize veya ikili veriler kesiliyor” dan sorumlu sütunları nasıl belirleyebilirim?


31

Uzak bir Pg veritabanından SELECT'e yazdığım kodla otomatik olarak bazı sorgular oluşturuyorum ve yerel bir SQL Server veritabanına ekliyorum. Ancak, onlardan biri bu hatayı oluşturuyor:

[Microsoft] [ODBC SQL Server Sürücüsü] [SQL Server] Dize veya ikili veri kesiliyor. (SQL-22001) [durum şimdi 22000’de 01000’di]

[Microsoft] [ODBC SQL Server Sürücüsü] [SQL Server] Beyanı sonlandırıldı. (SQL-01000). \ İnsert.pl satır 106'da.

Hangi sütunun bu hatayı oluşturduğunu ve girdi için uzunluğu eksik olduğunu nasıl öğrenirim? Bunu kaba kuvvetle tahmin etmeden yapmanın bir yolu var mı varchar?

Yanıtlar:


35

Hayır, hiçbir yere giriş yapılmadı. Oy verin ve iş durumunuzu belirtin; bu, SQL Server'da düzeltilmesi gereken uzun listede bir tanesidir.

Bu, yıllar önce Connect'te (muhtemelen önce SQL Server 2000 veya 2005 zaman diliminde), sonra da yeni geribildirim sisteminde talep edildi:

Ve şimdi, SQL Server 2019'da , SQL Server 2017 CU12'de teslim edildi ve gelecekteki bir SQL Server 2016 SP2 CU'da görünecektir.

SQL Server 2019 ilk kamu CTP olarak, sadece izleme bayrağı 460. tür gizli Bu sesler altında yüzeyleri, ancak yayımlandı içerik broşürü bu Microsoft . Bu ileriye dönük varsayılan davranış olacaktır (izleme bayrağı gerekli değildir), ancak bunu yeni bir veritabanı kapsamlı yapılandırma ile kontrol edebileceksiniz VERBOSE_TRUNCATION_WARNINGS.

İşte bir örnek:

USE tempdb;
GO
CREATE TABLE dbo.x(a char(1));

INSERT dbo.x(a) VALUES('foo');
GO

SQL Server 2019'dan önceki tüm desteklenen sürümlerde sonuç:

Mesaj 8152, Seviye 16, Durum 30, Satır 5
Dize veya ikili veriler kesilecektir.
Açıklama sonlandırıldı.

Şimdi, SQL Server 2019 CTP'lerinde izleme bayrağı etkin durumda:

DBCC TRACEON(460);
GO

INSERT dbo.x(a) VALUES('foo');
GO
DROP TABLE dbo.x;
DBCC TRACEOFF(460);

Sonuç tablo, sütun ve ( kesilmiş , dolu değil ) değerini gösterir:

Mesaj 2628, Seviye 16, Durum 1, Satır 11
Dize veya ikili veriler, 'tempdb.dbo.x', 'a' sütunu tablosunda kesilecektir. Kesilmiş değer: 'f'.
Açıklama sonlandırıldı.

Her şeyi bırakıp SQL Server 2019 veya Azure SQL Veritabanı hareket yükseltebilirsiniz kadar aslında dan MAX_LENGTH çekmeye, size "automagic" kodunu değiştirebilir sys.columnsyine orada almak ve sonra uygulanması gereken ismiyle birlikte LEFT(column, max_length)veya PG'nin karşılığı her ne ise. Veya, bu yalnızca sessizce veri kaybedeceğiniz anlamına geldiğinden, hangi sütunların uyuşmadığını bulun ve hedef sütunları kaynaktaki tüm verilere uyacak şekilde düzeltin. Her iki sisteme de meta veri erişimi ve zaten kaynak -> hedef sütunlarıyla otomatik olarak eşleşmesi gereken bir sorgu yazdığınız gerçeği göz önüne alındığında (aksi halde bu hata en büyük probleminiz olmaz), kaba kuvvet uygulamamalısınız hiç tahmin etmiyorum.


2

SQL Server Management Studio'dan SQL Server Alma ve Verme Sihirbazı'nı çalıştırma erişiminiz varsa (sağ tıklayın veritabanı> Görevler> Verileri İçe Aktar ...), sorgunuzu hedefe veri kaynağı olarak kullanarak SQL Client'tan içe aktarılan bir görev oluşturun tablo.

İçe aktarmayı çalıştırmadan önce, veri eşlemesini inceleyebilirsiniz ve size hangi sütunların tutarsız alan türlerine sahip olduğunu söyler. İçe aktarma görevini çalıştırırsanız, hangi sütunların içe aktarılmadığını size söyleyecektir.

Örnek Doğrulama Uyarısı:

Uyarı 0x802092a7: Veri Akışı Görev 1: 316 ile "NARRATIVE" veri tabanı sütununa, uzunluğu 316 ile "NARRATIVE" veri tabanı sütununa veri eklenmesi nedeniyle kesilme oluşabilir. (SQL Server Alma ve Verme Sihirbazı)


1

Sonuçta, sütun bilgisini kendim yazmadan almanın bir yolunu bulamadım.

Bu hata mesajı tarafından oluşturuldu DBD::ODBC, ancak yine de kullanabilirsiniz sys.columns (max_length)(Nasıl yapılacağını bilmiyorum).

Bu gibi kodları sütun listemin üzerinde iki elemanlı bir dizinin listesini almak için kullandım COLUMN_NAME, ve MAX_LENGTH( DBIcolumn_info() belgesinde ).

my @max_lengths = map [ @{$_->fetchall_arrayref->[0]}[3,6] ]
    , map $dbh_mssql->column_info('database', 'dbo', $dest_table, $_)
    , @col_mssql
;

Sonra istisnaları yakaladım ve INSERTişe yarar bir şey bastım. Bu örnekte @$row, gönderilen veristh->execute()

if ($@) {
        warn "$@\n";
        for ( my $idx=0; $idx <= $#{ $row }; $idx++ ) {
                Dumper {
                        maxlength => $max_lengths[$idx]->[1]
                        , name    => $max_lengths[$idx]->[0]
                        , length  => length( $row->[$idx] )
                        , content => $row->[$idx]
                };
        }
        die;
}

Ayrıca, lütfen diğer cevabı oylayın ve oy verin


2
Kod referanslamada bulunmadım, sys.columnsçünkü sorgularınızı "otomatik olarak" oluşturmak için hangi kodu kullandığınızı kesinlikle bilmiyordum. Gerçekten de, kodunuza dahil etmekle ilgili tahmin edebileceğimden çok daha karmaşık değil SELECT name, object_id, max_length FROM sys.columns;. Zaten bunu yapmak zorunda olan otomatik bir kodunuz olduğundan - ya da buna benzer bir şey - bir örneğin gerekli olduğunu düşünmedim.
Aaron Bertrand

sys.columnsAynı olan iki sütunla nasıl çalıştığından emin değilim name. Ayrıca kütüphaneyi kullanarak çalışmak yerine bir şey buldum sys, neden bunu seçilen cevap olarak yapalım? Microsoft SQL doesn't have x, do y insteadBu geçerli bir katkıdır, ancak eğer ybenim benden daha düşükse, yfarklı bir şey yapacağım ve bunu seçilen şekilde işaretleyeceğim.
Evan Carroll,

1
Sorunuz, esasen, hangi sütunun hatayı oluşturduğunu nasıl öğrenebilirim (büyük olasılıkla, çözümü yeniden yapılandırmak yerine o noktayı düzeltebilirsiniz). Size nereye bakacağınızı söyledim: sys.columns. Kaynak sütun uzunluklarınızı hedef sütun uzunluklarıyla karşılaştırmanız gereken tam olarak nerede. Bunu nasıl yaptığın sana kalmış. Kodunuzu nasıl düzelteceğinizi size söylemedim, çünkü otomajik sorgunuzun ilk başta nasıl oluşturulduğuna dair hiçbir fikrim yok, bu yüzden, dediğim gibi, önceden yaptığınız herhangi bir sorguya uzunluk saptamalarını nasıl ekleyeceğimi bilmiyordum. .
Aaron Bertrand

1

Nihayet Microsoft anlamlı bilgiler sağlamaya karar için String or binary would be truncatedSQL Server 2016 SP2 CU, SQL Server 2017 CU12 gelen ve SQL Server 2019 yılında başlayan.

Bilgi şimdi hem rahatsız edici tablo sütunu (tam nitelikli ad) hem de rahatsız edici değeri (120 karakterde kesilmiş) içerir:

Mesaj 2628, Seviye 16, Durum 1, Satır x Dize veya ikili veriler, 'TheDb.TheSchema.TheTable', 'TheColumn' sütununda kesilecektir. Kesilmiş değer: '...'. Açıklama sonlandırıldı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.