זהירות, SP_RENAME!

January 10, 2016

 

אורי קליל החורש

 

מומחה SQL Server בעל כ-15 שנות ניסיון מגוון בתחום.

DBA בחברה מתמחה בפיתוח טכנולוגיות חדשניות לקידום תעשיית הרפואה מטעם נאיה טכנולוגיות.

 

כל DBA  מתחיל מכיר את פקודת T-SQL בשם sp_rename שמטרתה לשנות שם של אובייקט. לא על זה באתי לכתוב, אלא על בעיה נסתרת שנגרמת מפקודה זו.

ההמשך עלול להישמע כמו באג, אבל האמת שמיקרוסופט מזהירה מזה ב MSDN, רק שקשה מאד להבין משם מה הבעיה. מתוך ה MSDN :

 

Renaming a stored procedure, function, view, or trigger will not change the name of the corresponding object name in the definitioncolumn of the sys.sql_modules catalog view. Therefore, we recommend that sp_rename not be used to rename these object types. Instead, drop and re-create the object with its new name.

 

 

 

אז מה הבעיה?

לפני תאור הבעיה אציין שבחברה בה אני נמצא כל פעם לאחר התקנת גרסה התקבלה תלונה שבמקרים מסוימים, ללא חוקיות נראית לעין, קוד ישן שמזמן כבר שונה ועודכן פתאום "חזר לחיים"!! זה קרה בעיקר בפרוצדורות וב views. בכל פעם שהבעיה קרתה לאחר מספר נסיונות לפתור אותה הבאנו קוד מתוקן מה source control והכל נרגע. עד לפעם הבאה...

הסתבר שהבעיה קשורה לנושא שלנו. כדי לסמלץ את הבעיה נריץ את הקוד הבא:

use tempdb

GO

 

if object_id('TestView') is not null

       drop view TestView_1

GO

if object_id('TestView_2') is not null

       drop view TestView_2

GO

 

create view TestView_1

as

       select 'No one can move me!' as view_desc

GO

 

exec sp_rename 'TestView_1', 'TestView_2'

GO

 

create view TestView_1

as

       select 'I did it !! I replaced the previous view!' as view_desc

GO

 

כעת אם נבדוק את תוכן ה Views:

 

select 'TestView_1' as View_Name, view_desc   from TestView_1

UNION ALL

select 'TestView_2' as View_Name, view_desc   from TestView_2

 

נקבל:

 

 

 

כעת יש שני views שונים במערכת, עם שמות שונים,תוכן שונה וקוד שונה. אולם אם נציץ בטבלת סיסטם sys.sql_modules, נראה את מה שהוזהרנו ב MSDN:

select object_name(object_id) as Object_name, definition

from sys.sql_modules

where object_name(object_id) like 'TestView%'

 

 

 

בשני המקרים הטקסט מתחיל ב Create View TestView_1! נראה רע, אבל זה עדיין לא הבעיה.

מסתבר שבסוף כל שדרוג, היה שלב בו קומפלו כל האובייקטים ב database, או במילים אחרות בוצע sp_refreshview לכל ה views במערכת.

כעת ננסה בדוגמה שלנו –

 exec sp_refreshview  TestView_2

 

ונבדוק שוב את תכולת ה views נקבל הפעם:

 

ז"א הקוד של testView_1 נדרס ע"י הקוד הישן שלו!

כאן יש בשורה קטנה, בין אם זה באג או לא, הבעיה שהוזכרה כאן ככל הנראה תוקנה בגרסאות SQL 2012 ומעלה, אם כי בטבלת sys.sql_modules עדיין קיים שם האובייקט הישן כמו שצוין מקודם.

אז מה אפשר לעשות? להיזהר מ sp_rename! איפה שאפשר לעשות drop/create ולא rename.

באופו אישי אני מציע לקחת את זה צעד אחד קדימה ולהגדיר נהל חד משמעי שאין ל"גבות" אובייקטים בתוך בסיס הנתונים בסביבת ייצור (הרי מי שעשה rename אני מניח שזו היתה כוונתו). ואגב זה נכון גם לגיבוי טבלאות שם מי שעושה rename  גורם לנזק גדול בהרבה!

אם בכל זאת נרצה לגבות אובייקטים מסויימים לפני שנדרוס אותם אפשר לגבות לקבצי טקסט או לבסיס נתונים אחר. את סביבת הייצור יש להשאיר נקייה.

Please reload

Featured Posts

I'm busy working on my blog posts. Watch this space!

Please reload

Recent Posts

October 31, 2017

October 29, 2017

Please reload

Archive
Please reload

Search By Tags