זהירות, SP_RENAME!
אורי קליל החורש
מומחה 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 גורם לנזק גדול בהרבה!
אם בכל זאת נרצה לגבות אובייקטים מסויימים לפני שנדרוס אותם אפשר לגבות לקבצי טקסט או לבסיס נתונים אחר. את סביבת הייצור יש להשאיר נקייה.
Comments