เพิ่มคอลัมน์ลงในตารางโดยมีค่าเริ่มต้นเท่ากับค่าของคอลัมน์ที่มีอยู่


94

จะเพิ่มคอลัมน์ลงในตาราง SQL Server ด้วยค่าเริ่มต้นที่เท่ากับค่าของคอลัมน์ที่มีอยู่ได้อย่างไร?

ฉันลองใช้คำสั่ง T-SQL นี้:

ALTER TABLE tablename 
ADD newcolumn type NOT NULL DEFAULT (oldcolumn) 

แต่มันให้ข้อผิดพลาด:

ไม่อนุญาตให้ใช้ชื่อ "คอลัมน์เก่า" ในบริบทนี้ นิพจน์ที่ถูกต้องคือค่าคงที่นิพจน์คงที่และตัวแปร (ในบางบริบท) ไม่อนุญาตให้ใช้ชื่อคอลัมน์


6
ค่าเริ่มต้นอาจเป็นค่าคงที่ไม่ใช่คอลัมน์อื่น ฉันคิดว่าสิ่งนี้ต้องการทริกเกอร์
ypercubeᵀᴹ

1
ตกลงฉันจะทำอย่างนั้นได้อย่างไรฉันยังใหม่กับ sql
dodos

1
จะเป็นค่าเริ่มต้นเสมอหรือเป็นเพียงการเติมข้อมูลคอลัมน์สำหรับแถวที่มีอยู่ในขณะที่คอลัมน์ใหม่จะถูกเพิ่มลงในตาราง
Damien_The_Unbeliever

1
@Damien_The_Unbeliever เพียงเพื่อเติมข้อมูลคอลัมน์สำหรับแถวที่มีอยู่
dodos

2
คุณต้องทำเป็นแยกUPDATEจากกันแล้วฉันกลัว
Damien_The_Unbeliever

คำตอบ:


73

ลองสิ่งนี้:

ALTER TABLE tablename ADD newcolumn type NOT NULL DEFAULT (0)
Go
Update tablename SET newcolumn = oldcolumn Where newcolumn = 0
Go

6
.. ใช่ แต่จะใช้ได้กับแถวที่มีอยู่เท่านั้น จะไม่ตั้งค่า [คอลัมน์ใหม่] เมื่อมีการแทรกแถวใหม่ คุณต้องใช้ทริกเกอร์ AFTER INSERT เป็นต้น
มิลาน

15
สิ่งนี้เพิ่มข้อ จำกัด เริ่มต้นที่ไม่ได้ตั้งใจบนโต๊ะ
Romain Vergnory

1
@RomainVergnory ฉันเห็นด้วยเป็นการดีกว่าที่จะไปโดยไม่มีข้อ จำกัด ที่จะ NOT NULL ในตอนแรกจากนั้นเติมค่าด้วยคอลัมน์ที่มีอยู่แล้วจึงเพิ่ม NOT NULL อีกครั้งใน
ภายหลัง

15

ฉันไม่ชอบพวกเขามากนัก แต่นี่คือวิธีที่คุณสามารถทำได้ด้วยAFTER INSERTทริกเกอร์:

CREATE TRIGGER TableX_AfterInsert_TRG 
  ON TableX 
AFTER INSERT
AS
  UPDATE TableX AS t
  SET t.newcolumn = t.oldcolumn
  FROM Inserted AS i
  WHERE t.PK = i.PK ;              -- where PK is the PRIMARY KEY of the table   

15

AFTER INSERTวิธีการทริกเกอร์เกี่ยวข้องกับค่าใช้จ่ายที่เกิดจากการเพิ่มUPDATEคำสั่ง ฉันขอแนะนำให้ใช้INSTEAD OF INSERTทริกเกอร์ดังนี้:

CREATE TRIGGER tablename_on_insert ON tablename 
INSTEAD OF INSERT 
AS
INSERT INTO tablename (oldcolumn, newcolumn)
SELECT oldcolumn, ISNULL(newcolumn, oldcolumn)
FROM inserted

สิ่งนี้ใช้ไม่ได้แม้ว่าoldcolumnคอลัมน์นี้จะเป็นคอลัมน์ข้อมูลประจำตัวอัตโนมัติ


2
INSTEAD OFทริกเกอร์ไม่ทำงานเมื่อใช้ตารางชั่วคราว:SYSTEM_VERSIONING = ON
CalvinDale

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

3

หากต้องการขยายคำตอบของKapilและหลีกเลี่ยงข้อ จำกัด เริ่มต้นที่ไม่ต้องการให้ลองทำดังนี้:

ALTER TABLE tablename ADD newcolumn type NOT NULL CONSTRAINT DF_TMP_TABLENAME_NEWCOLUMN DEFAULT -9999
Go
Update tablename SET newcolumn = oldcolumn
Go
ALTER TABLE tablename DROP CONSTRAINT DF_TMP_TABLENAME_NEWCOLUMN
Go

แทนที่ -9999 ด้วย 'noData' หากประเภทของคุณคือ varchar, nvarchar, datetime, ... หรือโดยข้อมูลที่เข้ากันได้สำหรับประเภทอื่น ๆ : ค่าเฉพาะไม่สำคัญมันจะถูกลบโดยคำสั่งที่ 2


2

คุณสามารถใช้คอลัมน์จากการคำนวณเพื่อแทรกคอลัมน์ใหม่ในตารางตามค่าคอลัมน์ที่มีอยู่

ALTER TABLE dbo.TableName ADD NewColumn AS (OldColumn) PERSISTED;

หรือหากคุณต้องการเปลี่ยนแปลงค่าตามค่าคอลัมน์ที่มีอยู่ให้ใช้

ALTER TABLE dbo.TableName ADD NewColumn AS (OldColumn * 1.5) PERSISTED;

นี่เป็นคำตอบที่ถูกต้องฉันคิดว่าคำตอบอย่างเป็นทางการกำลังอัปเดตเพียงครั้งเดียววิธีที่ถูกต้องคือทำให้เป็นเวลานานและสม่ำเสมอ
Kat Lim Ruiz

0

สำหรับกรณีของฉันฉันต้องการเพิ่มคอลัมน์ใหม่ที่ไม่ซ้ำกันที่ไม่เป็นโมฆะชื่อ CODE แต่ฉันไม่รู้เกี่ยวกับค่าในเวลาสร้าง ฉันตั้งค่าเริ่มต้นโดยรับค่าเริ่มต้นจาก NewID () แล้วอัปเดตในภายหลัง

ALTER TABLE [WIDGET] ADD [CODE] CHAR(5) NOT NULL DEFAULT(SUBSTRING(CONVERT(CHAR(36), NEWID()), 1, 5))

ALTER TABLE [dbo].[WIDGET] WITH CHECK ADD CONSTRAINT [UQ_WIDGET_CODE] UNIQUE ([CODE])

-3

ฉันคิดว่ามันจะทำงานถ้าคุณใช้Set Identity_Insert <TableName> OFFและหลังคำสั่ง INSERT Set Identity_Insert <TableName> ONที่คุณเขียนเพียงแค่ใช้

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