Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Fitur usang untuk dikeluarkan dari kotak peralatan Anda – Bagian 3

Saya baru-baru ini membahas beberapa fitur yang disarankan Microsoft untuk tidak digunakan, dan saya pikir Anda juga harus melupakan keberadaan. Ada kasus di mana seorang rekan terus-menerus mempromosikan tampilan kompatibilitas mundur yang tidak digunakan lagi sys.sysprocesses alih-alih tampilan manajemen dinamis (DMV) yang lebih baru, dan kasus lain di mana rekan yang berbeda menghapus server produksi menggunakan SQL Server Profiler.

Run-in terbaru saya dengan hal-hal yang paling dilupakan adalah prosedur tersimpan baru dengan ntext parameter. Saya memeriksa dan, tentu saja, tipe datanya cocok dengan skema untuk tabel yang mendasarinya. Pikiran saya mulai berpacu dengan tipe data yang lebih lama ini untuk menjelaskan mengapa kita seharusnya tidak menggunakannya lagi:

  • gambar
  • nteks
  • teks

Jenis ini ada dalam daftar usang karena berbagai alasan, dan telah menempati tempat permanen dalam daftar itu sejak diganti dengan max jenis cara kembali di SQL Server 2005. Beberapa poin nyeri ini meliputi:

  • Anda tidak dapat menggunakan banyak fungsi string, seperti LEFT() , RTRIM() , UPPER() , dan sebagian besar operator pembanding;
  • Anda perlu menggunakan fungsi seperti TEXTPTR , WRITETEXT , dan UPDATETEXT untuk modifikasi;
  • Anda tidak dapat menggunakan tipe sebagai variabel lokal;
  • Anda tidak dapat mereferensikan kolom di DISTINCT , GROUP BY , ORDER BY , atau sebagai kolom yang disertakan (bukan berarti Anda ingin melakukan salah satu dari ini);
  • nilai yang lebih kecil yang dapat ditampung dalam baris hanya dapat dilakukan dengan text in row pilihan.

Itu bukan daftar yang lengkap; ada perbedaan lain yang mungkin Anda anggap kurang lebih penting. Alasan paling mendesak bagi saya adalah Anda tidak dapat membangun kembali indeks berkerumun secara online jika tabel berisi salah satu tipe data ini.

Mari kita buat database sederhana dengan beberapa tabel:

CREATE DATABASE BadIdeas;
GO
 
USE BadIdeas;
GO
 
CREATE TABLE dbo.t1(id bigint IDENTITY PRIMARY KEY, msg nvarchar(max));
CREATE TABLE dbo.t2(id bigint IDENTITY PRIMARY KEY, msg ntext);

Sekarang, mari kita coba melakukan operasi online pada tabel:

ALTER TABLE dbo.t1 REBUILD WITH (ONLINE = ON);
GO
ALTER TABLE dbo.t2 REBUILD WITH (ONLINE = ON);

Saat pernyataan pertama berhasil, pernyataan kedua menghasilkan pesan kesalahan seperti ini:

Msg 2725, Level 16, State 2
Operasi online tidak dapat dilakukan untuk indeks 'PK__t2__3213E83FEEA1E0AD' karena indeks berisi kolom 'msg' dari tipe data teks, ntext, gambar atau FILESTREAM. Untuk indeks yang tidak berkerumun, kolom tersebut dapat berupa kolom sertakan dari indeks. Untuk indeks berkerumun, kolomnya bisa berupa kolom apa saja dari tabel. Jika DROP_EXISTING digunakan, kolom dapat menjadi bagian dari indeks baru atau lama. Operasi harus dilakukan secara offline.

Dalam skenario satu kali, pesan kesalahan cukup mudah untuk ditangani:Anda melewatkan tabel atau, jika tabel benar-benar harus dibangun kembali, Anda bekerja dengan tim Anda untuk menjadwalkan pemadaman. Saat Anda mengotomatiskan solusi pemeliharaan indeks atau menerapkan setelan kompresi baru di seluruh lingkungan Anda, membuat solusi Anda menangani keadaan saat ini atau di masa mendatang akan lebih merepotkan.

Apa yang harus dilakukan?

Anda dapat mulai mengganti kolom ini dengan kolom yang lebih modern. Berikut adalah kueri untuk membantu Anda melacaknya menggunakan sys.columns tampilan katalog, tetapi Anda sendirian untuk mencari referensi eksplisit yang mungkin ada dalam kode aplikasi Anda:

SELECT [Schema]    = s.name, 
       [Object]    = o.name,
       [Column]    = c.name,
       [Data Type] = TYPE_NAME(c.user_type_id) + CASE 
         WHEN c.system_type_id <> c.user_type_id 
         THEN N' (' + TYPE_NAME(c.system_type_id) + N')' 
         ELSE N'' END
  FROM sys.columns AS c
  INNER JOIN sys.objects AS o
    ON c.[object_id] = o.[object_id]
  INNER JOIN sys.schemas AS s
    ON o.[schema_id] = s.[schema_id]
  WHERE c.system_type_id IN (34, 35, 99)
  ORDER BY [Schema], [Object], [Column];

Keluaran:

Mungkin tergoda untuk masuk ke SSMS dan secara manual mengubah tipe data kolom ini, tetapi mungkin ada implikasi lain juga. Misalnya, kolom mungkin memiliki batasan default yang terkait dengannya. Dan Anda mungkin memiliki prosedur tersimpan dengan parameter yang harus diperbarui secara bersamaan:

CREATE PROCEDURE dbo.sp1 @p1 ntext AS PRINT 1;
GO

Untuk menemukan semua kasus ini, Anda dapat menyesuaikan kueri di atas untuk menelusuri sys.parameters lihat katalog sebagai gantinya:

SELECT [Schema]  = s.name, 
       [Object]   = o.name, 
       [Parameter] = p.name, 
       [Data Type] = TYPE_NAME(p.user_type_id) + CASE 
         WHEN p.system_type_id <> p.user_type_id 
         THEN N' (' + TYPE_NAME(p.system_type_id) + N')' 
         ELSE N'' END
  FROM sys.objects AS o
  INNER JOIN sys.schemas AS s
    ON o.[schema_id] = s.[schema_id]
  INNER JOIN sys.parameters AS p
    ON p.[object_id] = o.[object_id]
  WHERE p.system_type_id IN (34, 35, 99)
  ORDER BY [Schema], [Object], [Parameter];

Keluaran:

Jika Anda perlu mengembalikan data ini di semua basis data, Anda dapat mengambil sp_ineachdb , prosedur yang saya tulis (dan didokumentasikan di sini dan di sini) untuk mengatasi beberapa keterbatasan dalam sp_MSforeachdb yang buggy, tidak berdokumen, dan tidak didukung . Kemudian Anda dapat melakukan ini:

EXEC master.dbo.sp_ineachdb @command = N'SELECT [Database]  = DB_NAME(), 
       [Schema]    = s.name, 
       [Object]    = o.name,
       [Column]    = c.name,
       [Data Type] = TYPE_NAME(c.user_type_id) + CASE 
         WHEN c.system_type_id <> c.user_type_id 
         THEN N'' ('' + TYPE_NAME(c.system_type_id) + N'')'' 
         ELSE N'''' END
  FROM sys.columns AS c
  INNER JOIN sys.objects AS o
    ON c.[object_id] = o.[object_id]
  INNER JOIN sys.schemas AS s
    ON o.[schema_id] = s.[schema_id]
  WHERE c.system_type_id IN (34, 35, 99)
  ORDER BY [Schema], [Object], [Column];
 
SELECT [Database]  = DB_NAME(),
       [Schema]    = s.name, 
       [Object]    = o.name, 
       [Parameter] = p.name, 
       [Data Type] = TYPE_NAME(p.user_type_id) + CASE 
         WHEN p.system_type_id <> p.user_type_id 
         THEN N'' ('' + TYPE_NAME(p.system_type_id) + N'')''
         ELSE N'''' END
  FROM sys.objects AS o
  INNER JOIN sys.schemas AS s
    ON o.[schema_id] = s.[schema_id]
  INNER JOIN sys.parameters AS p
    ON p.[object_id] = o.[object_id]
  WHERE p.system_type_id IN (34, 35, 99)
  ORDER BY [Schema], [Object], [Parameter];';

Catatan tambahan yang menarik di sini:jika Anda menjalankannya terhadap semua database, Anda akan menemukan bahwa, bahkan di SQL Server 2019, Microsoft masih menggunakan beberapa tipe lama ini.

Anda dapat mengotomatiskannya lebih lanjut dengan menjalankannya dari PowerShell atau alat otomatisasi apa pun yang Anda gunakan untuk mengelola beberapa contoh SQL Server.

Tentu saja, itu baru permulaan – hanya menghasilkan daftar. Anda dapat memperluasnya lebih jauh untuk menghasilkan versi draf dari ALTER TABLE perintah yang Anda perlukan untuk memperbarui semua tabel, tetapi perintah itu perlu ditinjau sebelum Anda menjalankannya, dan Anda masih perlu memodifikasi sendiri prosedurnya (menghasilkan ALTER PROCEDURE perintah yang hanya memiliki nama tipe parameter yang diganti dengan benar bukanlah latihan yang mudah dengan cara apa pun). Berikut adalah contoh yang menghasilkan ALTER TABLE perintah, dengan mempertimbangkan nullability tetapi tidak ada komplikasi lain seperti batasan default:

SELECT N'ALTER TABLE ' + QUOTENAME(s.name)
  + N'.' + QUOTENAME(o.name)
  + N' ALTER COLUMN ' + QUOTENAME(c.name) + N' '
  + CASE c.system_type_id
      WHEN 34 THEN N'varbinary'
      WHEN 35 THEN N'varchar'
      WHEN 99 THEN N'nvarchar'
    END + N'(max)' 
  + CASE c.is_nullable 
      WHEN 0 THEN N' NOT' 
      ELSE N'' END + N' NULL;'
FROM sys.columns AS c
INNER JOIN sys.objects AS o
  ON c.[object_id] = o.[object_id]
INNER JOIN sys.schemas AS s
  ON o.[schema_id] = s.[schema_id]
  WHERE c.system_type_id IN (34, 35, 99);

Keluaran:

ALTER TABLE [dbo].[t2] ALTER COLUMN [msg] nvarchar(max) NULL;

Dan jika Anda bertanya-tanya, tidak, Anda tidak dapat melakukan operasi satu kali ini dengan WITH (ONLINE = ON) eksplisit pilihan:

Msg 11427, Level 16, State 1
Operasi ALTER COLUMN online tidak dapat dilakukan untuk tabel 't2' karena kolom 'msg' saat ini telah atau sedang diubah menjadi tipe data yang tidak didukung:teks, ntext, gambar, tipe CLR atau FILESTREAM. Operasi harus dilakukan secara offline.

Kesimpulan

Mudah-mudahan ini memberikan latar belakang yang bagus tentang mengapa Anda ingin menghilangkan tipe yang tidak digunakan lagi ini, dan titik awal untuk benar-benar membuat perubahan. Microsoft belajar dengan susah payah bahwa tidak banyak fungsi yang dapat mereka cabut begitu saja dari produk, jadi saya tidak khawatir bahwa ini akan benar-benar tidak ada lagi dalam hidup saya. Namun rasa takut akan pemecatan seharusnya tidak menjadi satu-satunya motivator Anda.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL, cara memperbarui data

  2. T-SQL Selasa #65 :Mengajarkan Sesuatu yang Baru

  3. Penghentian Salesforce TLS 1.0

  4. Cara Menjadi Desainer Basis Data

  5. Menggunakan Folder Kerja ke Basis Data Kontrol Sumber