การเปลี่ยนการใช้ GETDATE () ในฐานข้อมูลทั้งหมด


27

ฉันต้องโยกย้ายฐานข้อมูล SQL Server 2017 ในสถานที่ไปยังฐานข้อมูล Azure SQL และฉันเผชิญกับความท้าทายบางอย่างเนื่องจากมีข้อ จำกัด อยู่บ้าง

โดยเฉพาะอย่างยิ่งเนื่องจากฐานข้อมูล Azure SQL ทำงานได้เฉพาะในเวลา UTC (ไม่มีเขตเวลา) และเราต้องการเวลาท้องถิ่นเราจึงต้องเปลี่ยนการใช้งานGETDATE() ทุกที่ในฐานข้อมูลซึ่งพิสูจน์แล้วว่าทำงานได้ดีกว่าที่คาดไว้

ฉันสร้างฟังก์ชันที่ผู้ใช้กำหนดเพื่อให้ได้เวลาท้องถิ่นที่ทำงานอย่างถูกต้องสำหรับเขตเวลาของฉัน:

CREATE FUNCTION [dbo].[getlocaldate]()
RETURNS datetime
AS
BEGIN
    DECLARE @D datetimeoffset;
    SET @D = CONVERT(datetimeoffset, SYSDATETIMEOFFSET()) AT TIME ZONE 'Pacific SA Standard Time';
    RETURN(CONVERT(datetime,@D));
END

ปัญหาที่ฉันมีปัญหาคือการเปลี่ยนแปลงจริง ๆGETDATE()กับฟังก์ชั่นนี้ในทุกมุมมองกระบวนงานที่เก็บไว้คอลัมน์ที่คำนวณได้ค่าเริ่มต้นข้อ จำกัด อื่น ๆ ฯลฯ

อะไรจะเป็นวิธีที่ดีที่สุดในการใช้การเปลี่ยนแปลงนี้

เราอยู่ในตัวอย่างของประชาชนในกรณีที่มีการจัดการ มันยังมีปัญหาเดียวกันกับGETDATE()ดังนั้นจึงไม่ช่วยแก้ไขปัญหานี้ การย้ายไปยัง Azure เป็นข้อกำหนด ฐานข้อมูลนี้ใช้ (และจะใช้) ตลอดเวลาในเขตเวลานี้

คำตอบ:


17
  1. ใช้เครื่องมือ SQL Server เพื่อส่งออกคำจำกัดความวัตถุฐานข้อมูลไปยังไฟล์ SQL ซึ่งควรรวมถึง: ตาราง, มุมมอง, ทริกเกอร์, SPs, ฟังก์ชั่นและอื่น ๆ

  2. แก้ไขไฟล์ SQL (สำรองข้อมูลก่อน) โดยใช้เท็กซ์เอดิเตอร์ที่อนุญาตให้คุณค้นหาข้อความ"GETDATE()"และแทนที่ด้วย"[dbo].[getlocaldate]()"

  3. เรียกใช้ไฟล์ SQL ที่แก้ไขใน Azure SQL เพื่อสร้างวัตถุฐานข้อมูลของคุณ ...

  4. ดำเนินการโยกย้ายข้อมูล

ที่นี่คุณมีการอ้างอิงจากเอกสารสีฟ้า: การสร้างสคริปต์สำหรับ SQL Azure


แม้ว่าในทางปฏิบัติวิธีนี้มีความซับซ้อนมากกว่าที่ฟัง แต่อาจเป็นคำตอบที่ถูกต้องและดีที่สุด ฉันต้องทำงานที่คล้ายกับหลาย ๆ ครั้งและฉันได้ลองทุกวิธีที่ใช้ได้และฉันไม่พบสิ่งใดที่ดีกว่า (หรือใกล้เคียงจริง ๆ ) วิธีการอื่น ๆดูดีในตอนแรก แต่พวกเขาก็กลายเป็นหล่มทารุณของการกำกับดูแลและ gotchas อย่างรวดเร็ว
RBarryYoung

15

อะไรจะเป็นวิธีที่ดีที่สุดในการใช้การเปลี่ยนแปลงนี้

ฉันจะหลีกเลี่ยงวิธีอื่น แปลงเวลาทั้งหมดของคุณในฐานข้อมูลเป็น UTC และใช้ UTC และไปตามโฟลว์ หากคุณต้องการเวลาประทับใน tz อื่นคุณสามารถสร้างคอลัมน์ที่สร้างโดยใช้AT TIME ZONE(ตามที่คุณทำด้านบน) ที่แสดงการประทับเวลาใน TZ ที่ระบุ (สำหรับแอป) แต่ฉันจะพิจารณาอย่างจริงจังว่าให้ UTC กลับไปที่แอปและเขียนตรรกะนั้น - ตรรกะการแสดงผล - ในแอป


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

5
คุณจะรับประกันอะไรได้บ้างว่าไม่มี "แอพและซอฟต์แวร์" ใช้ getdate ()? เช่นรหัส sql ที่ฝังอยู่ในแอพ หากคุณไม่สามารถรับประกันได้ว่าการปรับฐานข้อมูลใหม่เพื่อใช้ฟังก์ชั่นที่แตกต่างกันก็จะนำไปสู่ความไม่สอดคล้องกัน
นาย Magoo

@MisterMagoo มันขึ้นอยู่กับแนวทางปฏิบัติที่ร้านค้าค่อนข้างตรงไปตรงมาฉันคิดว่านี่เป็นข้อกังวลเล็กน้อยมากและฉันไม่สามารถเห็นเวลาที่จะถามคำถามเพื่อแก้ปัญหาแล้วจึงแก้ไขฉันจริง ๆ มันจะน่าสนใจหากคำถามนี้ไม่ใช่ Azure เพราะฉันสามารถแฮ็คและให้ข้อเสนอแนะเพิ่มเติม สิ่งที่มีเมฆดูด: พวกเขาไม่สนับสนุนดังนั้นคุณต้องเปลี่ยนบางสิ่งที่อยู่ข้างคุณ ฉันอยากไปเส้นทางที่ให้ไว้ในคำตอบและใช้เวลาทำอย่างถูกต้อง นอกจากนี้คุณไม่รับประกันอะไรเลยที่จะทำงานเมื่อคุณย้ายไปที่ Azure เช่นเคย
Evan Carroll

@EvanCarroll ขอโทษฉันเพิ่งอ่านความคิดเห็นของฉันอีกครั้งและฉันไม่ได้แสดงเจตนาดี! ฉันต้องการสนับสนุนคำตอบของคุณ (upvoted) และเพิ่มจุดที่คำแนะนำในการเปลี่ยนการใช้ getdate () เป็น getlocaldate () ในฐานข้อมูลจะทำให้พวกเขาเปิดให้ไม่สอดคล้องกันจากด้านแอพและยิ่งกว่านั้นเป็นเพียง ติดปูนปลาสเตอร์กับปัญหาที่ใหญ่กว่า เห็นด้วยกับคำตอบของคุณ 100% การแก้ไขปัญหาหลักคือแนวทางที่ถูกต้อง
นาย Magoo

@MisterMagoo ฉันเข้าใจความกังวลของคุณ แต่ในกรณีนี้ฉันสามารถรับประกันได้ว่าแอพและซอฟต์แวร์จะมีปฏิสัมพันธ์กับฐานข้อมูลผ่านขั้นตอนการจัดเก็บเท่านั้น
Lamak

6

แทนที่จะส่งออกแก้ไขด้วยตนเองและรันซ้ำคุณสามารถลองทำงานโดยตรงในฐานข้อมูลด้วยบางสิ่งเช่น:

DECLARE C CURSOR FOR
        SELECT sm.definition, so.type
        FROM   sys.objects so
        JOIN   sys.all_sql_modules sm ON sm.object_id = so.object_id
        WHERE  so.type IN ('P', 'V')
        ORDER BY so.name
DECLARE @SQL NVARCHAR(MAX), @ojtype NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL, @ojtype
WHILE @@FETCH_STATUS = 0 BEGIN
    IF @objtype = 'P' SET @SQL = REPLACE(@SQL, 'CREATE PROCEDURE', 'ALTER PROCEDURE') 
    IF @objtype = 'V' SET @SQL = REPLACE(@SQL, 'CREATE VIEW'     , 'ALTER VIEW'     ) 
    SET @SQL = REPLACE(@SQL, 'GETDATE()', '[dbo].[getlocaldate]()') 
    --PRINT @SQL
    EXEC (@SQL)
    FETCH NEXT FROM C INTO @SQL, @ojtype
END
CLOSE C
DEALLOCATE C

แน่นอนมันขยายออกไปเพื่อจัดการกับฟังก์ชั่นทริกเกอร์และอื่น ๆ ด้วย

มีข้อแม้อยู่เล็กน้อย:

  • คุณอาจจะต้องมีสว่างบิตและจัดการกับแตกต่างกัน / พิเศษพื้นที่สีขาวระหว่างCREATEและPROCEDURE/ /VIEW <other>มากกว่าREPLACEการที่คุณอาจต้องการแทนที่จะทิ้งCREATEในสถานที่และดำเนินการDROPครั้งแรก แต่ความเสี่ยงนี้ออกsys.dependsและเพื่อน ๆ ออกจาก kilter ที่ALTERอาจไม่ได้ถ้าALTERล้มเหลวอย่างน้อยคุณมีวัตถุที่มีอยู่ยังคงอยู่ในสถานที่ที่มีDROP+ CREATEคุณอาจ ไม่.

  • หากโค้ดของคุณมีกลิ่น "ฉลาด" เช่นการปรับเปลี่ยนสคีมาของตนเองด้วย ad-hoc TSQL คุณจะต้องตรวจสอบให้แน่ใจว่าการค้นหาและแทนที่CREATE-> ALTERไม่รบกวนการทำงาน

  • คุณจะต้องการทดสอบการถดถอยทั้งแอปพลิเคชันหลังจากการดำเนินการไม่ว่าคุณจะใช้เคอร์เซอร์หรือวิธีการส่งออก + แก้ไข + เรียกใช้

ฉันใช้วิธีนี้เพื่อทำการปรับปรุงแบบแผนแบบกว้างที่คล้ายกันในอดีต มันเป็นบิตของการแฮ็คและรู้สึกค่อนข้างน่าเกลียด แต่บางครั้งมันเป็นวิธีที่ง่ายที่สุด / เร็วที่สุด

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

DECLARE C CURSOR FOR
        SELECT AlterDefaultSQL = 'ALTER TABLE [' +st.name+ '] DROP CONSTRAINT [' + si.name + '];'
                               + CHAR(10)
                               + 'ALTER TABLE [' +st.name+ '] ADD CONSTRAINT [' + si.name + '] DEFAULT '+REPLACE(si.definition, 'GETDATE()', '[dbo].[getlocaldate]()')+' FOR '+sc.name+';'
        FROM   sys.tables st
        JOIN   sys.default_constraints si ON si.parent_object_id = st.object_id
        JOIN   sys.columns sc ON sc.default_object_id = si.object_id
DECLARE @SQL NVARCHAR(MAX)
OPEN C
FETCH NEXT FROM C INTO @SQL
WHILE @@FETCH_STATUS = 0 BEGIN
    --PRINT @SQL
    EXEC (@SQL)
    FETCH NEXT FROM C INTO @SQL
END
CLOSE C
DEALLOCATE C

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


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

ค่าเริ่มต้นของคอลัมน์และข้อ จำกัด อื่น ๆ ยังสามารถสแกนได้ในsysสคีมาและการปรับเปลี่ยนทางโปรแกรม
David Spillett

อาจแทนที่ด้วยเช่นCREATE OR ALTER PROCEDUREช่วยในการแก้ไขปัญหาการสร้างรหัสบางอย่าง; อาจยังมีปัญหาเนื่องจากคำจำกัดความที่เก็บไว้จะอ่านCREATE PROCEDURE(สามช่องว่าง) และสิ่งนี้ไม่ตรงกันCREATE PROCEDUREหรือCREATE OR ALTER PROCEDURE… ._
TheConstructor

@TheConstructor - นั่นคือสิ่งที่ฉันหมายถึง WRT "ช่องว่างพิเศษ" คุณสามารถหลีกเลี่ยงสิ่งนี้ได้ด้วยการเขียนฟังก์ชั่นที่สแกนหาสิ่งแรกCREATEที่ไม่ได้อยู่ในความคิดเห็นและแทนที่มัน ก่อนหน้านี้ฉันไม่ชอบ / สิ่งนี้ที่คล้ายกัน แต่ไม่มีรหัสของฟังก์ชั่นที่สะดวกในการโพสต์ในขณะนี้ หรือถ้าคุณสามารถรับประกันไม่มีคำจำกัดความของวัตถุของคุณมีความคิดเห็นก่อนหน้านี้ไม่สนใจปัญหาความคิดเห็นและเพียงแค่ค้นหาและแทนที่ตัวอย่างแรกของCREATE CREATE
David Spillett

ฉันได้ลองวิธีนี้ด้วยตัวเองหลายครั้งในอดีตและในแบบสมดุลวิธีการสร้าง - สคริปต์นั้นดีกว่าและเกือบจะเป็นสิ่งที่ฉันใช้ในทุกวันนี้เว้นแต่ว่าจำนวนวัตถุที่จะเปลี่ยนจะค่อนข้างเล็ก
RBarryYoung

5

ฉันชอบคำตอบของเดวิดและลงมือทำอย่างเป็นโปรแกรมในการทำสิ่งต่าง ๆ

แต่คุณสามารถลองวันนี้เพื่อรับการทดสอบใน Azure ผ่าน SSMS:

คลิกขวาที่ฐานข้อมูลของคุณ -> งาน -> สร้างสคริปต์ ..

[เรื่องย้อนหลัง] เรามีรุ่นน้อง DBA ที่อัพเกรดสภาพแวดล้อมการทดสอบทั้งหมดของเราเป็น SQL 2008 R2 ในขณะที่สภาพแวดล้อมการผลิตของเราอยู่ที่ SQL 2008 มันเป็นการเปลี่ยนแปลงที่ทำให้ฉันประจบประแจงมาจนถึงทุกวันนี้ ในการโยกย้ายไปสู่การผลิตจากการทดสอบเราต้องสร้างสคริปต์ภายใน SQL โดยใช้สคริปต์สร้างและในตัวเลือกขั้นสูงเราใช้ตัวเลือก 'ประเภทของข้อมูลไปยังสคริปต์: Schema และ Data' เพื่อสร้างไฟล์ข้อความขนาดใหญ่ เราสามารถย้ายฐานข้อมูลทดสอบ R2 ของเราไปยังเซิร์ฟเวอร์ SQL 2008 รุ่นเก่าได้สำเร็จซึ่งการคืนค่าฐานข้อมูลไปเป็นรุ่นที่ต่ำกว่าจะไม่ทำงาน เราใช้ sqlcmd เพื่อป้อนไฟล์ขนาดใหญ่ - เนื่องจากไฟล์มักมีขนาดใหญ่เกินไปสำหรับบัฟเฟอร์ข้อความ SSMS

สิ่งที่ฉันกำลังพูดอยู่ที่นี่คือตัวเลือกนี้อาจใช้ได้สำหรับคุณเช่นกัน คุณเพียงแค่ต้องทำหนึ่งขั้นตอนเพิ่มเติมแล้วค้นหาและแทนที่ getdate () ด้วย [dbo] .getlocaldate ในไฟล์ข้อความที่สร้างขึ้น (ฉันจะใส่ฟังก์ชั่นของคุณในฐานข้อมูลก่อนที่จะทำการโยกย้าย)

(ฉันไม่เคยต้องการที่จะมีความเชี่ยวชาญในการช่วยเหลือวงดนตรีของการกู้คืนฐานข้อมูล แต่ในขณะที่มันกลายเป็นวิธี defacto ในการทำสิ่งต่าง ๆ และมันทำงานได้ทุกครั้ง)

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

ป้อนคำอธิบายรูปภาพที่นี่


1

แก้ไข proc และ udf ทั้งหมดแบบไดนามิกเพื่อเปลี่ยนค่า

    DECLARE @Text   NVARCHAR(max), 
        @spname NVARCHAR(max), 
        @Type   CHAR(5), 
        @Sql    NVARCHAR(max) 
DECLARE @getobject CURSOR 

SET @getobject = CURSOR 
FOR SELECT sc.text, 
           so.NAME, 
           so.type 
    FROM   sys.syscomments sc 
           INNER JOIN sysobjects so 
                   ON sc.id = so.id 
    WHERE  sc.[text] LIKE '%getdate()%' 

--and type in('P','FN') 
OPEN @getobject 

FETCH next FROM @getobject INTO @Text, @spname, @Type 

WHILE @@FETCH_STATUS = 0 
  BEGIN 
      IF ( @Type = 'P' 
            OR @Type = 'FN' ) 
        SET @Text = Replace(@Text, 'getdate', 'dbo.getlocaldate') 

      SET @Text = Replace(@Text, 'create', 'alter') 

      EXECUTE Sp_executesql 
        @Text 

      PRINT @Text 

      --,@spname,@Type 
      FETCH next FROM @getobject INTO @Text, @spname, @Type 
  END 

CLOSE @getobject 

DEALLOCATE @getobject  

 

    CREATE PROCEDURE [dbo].[Testproc1] 
AS 
    SET nocount ON; 

  BEGIN 
      DECLARE @CurDate DATETIME = Getdate() 
  END

สังเกตเห็นความเห็นsysobjects ประเภทคอลัมน์เงื่อนไขสคริปต์ของฉันจะเปลี่ยนเพียง proc และ UDF

สคริปต์นี้จะแก้ไขทั้งหมดDefault Constraintที่มีGetDate()

    DECLARE @TableName      VARCHAR(300), 
        @constraintName VARCHAR(300), 
        @colName        VARCHAR(300), 
        @Sql            NVARCHAR(max) 
DECLARE @getobject CURSOR 

SET @getobject = CURSOR 
FOR SELECT ds.NAME, 
           sc.NAME AS colName, 
           so.NAME AS Tablename 
    --,ds.definition 
    FROM   sys.default_constraints ds 
           INNER JOIN sys.columns sc 
                   ON ds.object_id = sc.default_object_id 
           INNER JOIN sys.objects so 
                   ON so.object_id = ds.parent_object_id 
    WHERE  definition LIKE '%getdate()%' 

OPEN @getobject 

FETCH next FROM @getobject INTO @constraintName, @colName, @TableName 

WHILE @@FETCH_STATUS = 0 
  BEGIN 
      SET @Sql = 'ALTER TABLE ' + @TableName 
                 + ' DROP CONSTRAINT ' + @constraintName + '; ' 
                 + Char(13) + Char(10) + '           ' + Char(13) + Char(10) + '' 
      SET @Sql = @Sql + ' ALTER TABLE ' + @TableName 
                 + ' ADD CONSTRAINT ' + @constraintName 
                 + '          DEFAULT dbo.GetLocaledate() FOR ' 
                 + @colName + ';' + Char(13) + Char(10) + '          ' + Char(13) 
                 + Char(10) + '' 

      PRINT @Sql 

      EXECUTE sys.Sp_executesql 
        @Sql 

      --,@spname,@Type 
      FETCH next FROM @getobject INTO @constraintName, @colName, @TableName 
  END 

CLOSE @getobject 

DEALLOCATE @getobject   

1

ฉันตอบ Evan Carrolls ได้มากขึ้นเพราะฉันคิดว่านี่เป็นทางออกที่ดีที่สุด ฉันไม่สามารถโน้มน้าวเพื่อนร่วมงานของฉันว่าพวกเขาควรเปลี่ยนรหัส C # จำนวนมากดังนั้นฉันจึงต้องใช้รหัสที่ David Spillett เขียน ฉันได้แก้ไขปัญหาสองสามอย่างเกี่ยวกับ UDFs, Dynamic SQL และ Schemas (ไม่ใช่รหัสทั้งหมดที่ใช้ "dbo.") เช่นนี้

DECLARE C CURSOR LOCAL STATIC FOR
        SELECT sm.definition, so.type
        FROM   sys.objects so
        JOIN   sys.all_sql_modules sm ON sm.object_id = so.object_id
        WHERE  so.type IN ('P', 'V')
        AND CHARINDEX('getdate()', sm.definition) > 0
        ORDER BY so.name

DECLARE @SQL NVARCHAR(MAX), @objtype NVARCHAR(MAX)
OPEN C
WHILE 1=1 BEGIN
    FETCH NEXT FROM C INTO @SQL, @objtype
    IF @@FETCH_STATUS <> 0 BREAK

    IF @objtype = 'P' SET @SQL = REPLACE(@SQL, 'CREATE PROCEDURE', 'ALTER PROCEDURE') 
    IF @objtype = 'P' SET @SQL = REPLACE(@SQL, 'CREATE   PROCEDURE', 'ALTER PROCEDURE') /* when you write "create or alter proc" */
    IF @objtype = 'V' SET @SQL = REPLACE(@SQL, 'CREATE VIEW'     , 'ALTER VIEW'     ) 
    IF CHARINDEX('getdate())''', @sql) > 0 BEGIN  /* when dynamic SQL is used */
        IF CHARINDEX('utl.getdate())''', @sql) = 0 SET @SQL = REPLACE(@SQL, 'GETDATE()', 'utl.getdate()') 
    end
    ELSE begin
        SET @SQL = REPLACE(@SQL, 'GETDATE()', 'CONVERT(DATETIME, CONVERT(datetimeoffset,  SYSDATETIME()) AT TIME ZONE ''Central Europe Standard Time'')') 
    end
    EXEC dbo.LongPrint @String = @sql    
    EXEC (@SQL)
END
CLOSE C
DEALLOCATE C

และข้อ จำกัด เริ่มต้นเช่นนี้:

DECLARE C CURSOR LOCAL STATIC FOR
        SELECT AlterDefaultSQL = 'ALTER TABLE [' +sch.name+ '].[' +st.name+ '] DROP CONSTRAINT [' + si.name + '];'
                               + CHAR(10)
                               + 'ALTER TABLE [' +sch.name+ '].[' +st.name+ '] ADD CONSTRAINT [' + si.name + '] DEFAULT '+REPLACE(si.definition, 'GETDATE()', 'CONVERT(DATETIME, CONVERT(datetimeoffset,  SYSDATETIME()) AT TIME ZONE ''Central Europe Standard Time'')')+' FOR '+sc.name+';'
        FROM   sys.tables st
        JOIN   sys.default_constraints si ON si.parent_object_id = st.object_id
        JOIN   sys.columns sc ON sc.default_object_id = si.object_id
        INNER JOIN sys.schemas sch ON sch.schema_id = st.schema_id
        WHERE CHARINDEX('getdate()', si.definition) > 0
        ORDER BY st.name, sc.name

DECLARE @SQL NVARCHAR(MAX)
OPEN C
WHILE 1=1 BEGIN
    FETCH NEXT FROM C INTO @SQL
    IF @@FETCH_STATUS <> 0 BREAK

    EXEC dbo.LongPrint @String = @sql  
    EXEC (@SQL)
    FETCH NEXT FROM C INTO @SQL
END
CLOSE C
DEALLOCATE C


UDF
คำแนะนำในการใช้ UDF ที่คืนวันที่และเวลาในวันนี้ดูดี แต่ฉันคิดว่ายังมีปัญหาเกี่ยวกับประสิทธิภาพของ UDF อยู่มากพอดังนั้นฉันเลือกที่จะใช้โซลูชัน AT TIME ZONE ที่ยาวและน่าเกลียดมาก

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