none
יצירת פונקציה ללא בדיקה האם אובייקטים שמשתמשים בהם בפונקציה קיימים RRS feed

  • שאלה

  • היי.

    יש ב-SQL הבדל בין יצירת פונקציות או VIEWS לבין יצירת SPs, שהוא שב-SP היצירה לא נכשלת אם קיימים בה אובייקטים שלא קיימים, ואילו בפונקציות או VIEWS כן נכשלת היצירה.

    האם יש אופציה לאפשר יצירת פונקציות\VIEWS ללא ההכשלה הזו?


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 12:18

תשובות

  • מה שמעניין ומעט אבסורדי זה שניתן למחוק אלמנטים בהם תלוי ה VIEW, אבל ביצירה שלו מתקבלת שגיאה אם הם לא קיימים.

    כך שאכן תמיד אפשר לבנות את האלמנטים בצורה זמנית -> ליצור את ה VIEW -> למחוק את האלמנטים הסמניים -> ליצור אלמנטים אמיתיים לפני ההרצה של ה VIEW או כל שימוש בו (או שמתקבלת שגיאה בנקודה זו)

    נראה לי שזה הפתרון כרגע אכן

    * לגבי הבדיקה אני ממליץ לך לבצע אותה עם בלוק TRY ולא עם תנאי מהסיבה הפשוטה שבלוק TRY יבצע את כל הבדיקות לגבי הצלחה בעוד בשטית IF אתה צריך לחשוב על כל הנתונים לבד ותמיד יכול להיות בעיה נוספת שלא חשבת עליה כמו למשל שהאובייקט טבלה למשל קיים אבל שדה מסויים שנחוץ לא קיים (בתוםך הבלוק TRY אפשר לבדוק עם IF אם רוצים)

    אני מניח שהנושא סגור אם כן :-)
    זמן טוב לעבור לאכול..

    • סומן כתשובה על-ידי itaigitt יום רביעי 31 אוגוסט 2011 06:22
    יום שלישי 30 אוגוסט 2011 16:45
    מנחה דיון

כל התגובות

  • אתה מתכוון ליצור למשל פונקציה על אלמנט שעדיין לא קיים ואשר בזמן ההרצה יהיה קיים. נכון?

    למשל לייצר פונקציה כללית שתקבל נתון של שם טבלה (אפילו אם טבלה זו עדיין לא קיימת) כפרמטר ובזמן ההרצה הפונקציה תפעל עליה

    הרעיון פשוט אם כן

    Using Dynamic SQL


    היה עוזר לדעת מה בדיוק הפעולה שאתה רוצה לבצע. בעקרון השיטה של DYNAMIC SQL יכולה לעזור לדברים הבסיסיים.
    יום שלישי 30 אוגוסט 2011 13:16
    מנחה דיון
  • היי.

    האמת שזו לא הייתה הכוונה.

    אני מייצר סקריפטים לעדכון DB.

    יש לי סקריפטים לטבלאות, VIEWS, פונקציות ו-SPS (בסדר הרצה הזה).

    אבל, יש מצבים בהם VIEW ישתמש בפונקציה (נדיר) או שפונקציה תשתמש בפונקציה שלא בטוח שתמיצא לפניה בסקריפט של הפונקציות (יותר שכיח).

    לכן, בהרצה הראשונה הסקריפט ייכשל, אבל בהרצה שניה הוא יצליח (כי האובייקט שלא היה קיים כבר יהיה קיים).

    השאלה היא אם אני יכול לנטרל את הבדיקה שהאובייקטים שמשמשים אותי בתוך הפונקציות\VIEWS קיימים (בזמן היצירה)?


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 13:22
  • למה לא להכניס הכל פשוט לבלוק TRY ובתוך הבלוק CATCH תריץ אותו שוב?

    זה יכול להתאים לך?

    יום שלישי 30 אוגוסט 2011 13:44
    מנחה דיון
  • זאת יכולה להיות אופציה מעניינת.

    בהנחה שאני לא רוצה לבדוק לכל אובייקט האם יש לו אובייקטים שקודמים לו או לא (יש הרבה אובייקטים....) זה אומר שאני צריך להכניס הכל לתוך ה-TRY-CATCH.

    ובמיוחד שיכולים להיות מצבים (גם אם נדירים) ש-VIEW חדש ישתמש בפונקציה חדשה, ואז הסקריפט של ה-VIEWS לא ירוץ בכל מקרה....

     

    האמת שקיוויתי שיש איזה SET משהו שאמור לסקריפט להתעלם מהבדיקה של קיימות אובייקטים ב-DB.... יש מצב?


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 13:51
  • אני לא בטוח שאני מבין כי למשל לייצר פונקציה שבתוכה יש שימוש באובייקט שאינו קיים הרי שאין בעיה

    alter Function Get_CountRowa(@TableName varchar(100))
    RETURNS int
    AS
    BEGIN
        Declare @MyCount int
        select @MyCount = COUNT(*) from dbo.DNames1111
        Return @MyCount
    END
    GO

    גם אם אין לי שום טבלה בשם DNames1111 הפונקציה נוצרת טוב
    רק בהרצה של הפונקציה אני מקבל הודעת שגיאה

    Invalid object name 'dbo.DNames1111'.

    לגבי VIEW זה משהו אחר

    אתה יכול להעלות דוגמה פשוטה ספציפית שמייצרת לך שגיאה וננסה לפתור אותה?

    יום שלישי 30 אוגוסט 2011 14:00
    מנחה דיון
  • -- ====================================================
    -- case 1, OK, no errors:
    -- ====================================================
    CREATE FUNCTION dbo.foo
    (
    @bar INT
    )
    RETURNS INT
    AS
    BEGIN
    RETURN (SELECT dbo.splunge(@bar));
    END
    GO
    CREATE FUNCTION dbo.splunge
    (
    @mort INT
    )
    RETURNS INT
    AS
    BEGIN
    RETURN (@mort * 2)
    END
    GO
    -- ====================================================
    -- case 2, OK, no errors:
    -- ====================================================
    CREATE FUNCTION [dbo].[udf_table_test] (@intValue int)
    RETURNS @Table TABLE (ID int)
    AS
    BEGIN
    INSERT INTO @Table (ID)
    SELECT StamTableId FROM CheckOptionTest2 WHERE StamTableId > @intValue
       RETURN
    END
    GO
    CREATE VIEW [dbo].[CheckOptionTest2]
    AS
    SELECT StamTableId, StamTableStr
    FROM StamTable
    WHERE colIntA > 2
    GO
    -- ====================================================
    -- case 3, NOT OK:
    -- ====================================================
    CREATE VIEW [dbo].[CheckOptionTest3]
    AS
    SELECT StamTableId, StamTableStr
    FROM CheckOptionTest4
    WHERE colIntA > 2
    GO
    CREATE VIEW [dbo].[CheckOptionTest4]
    AS
    SELECT StamTableId, StamTableStr
    FROM StamTable
    WHERE colIntA > 4
    GO
    ERROR MSG:
    Msg 208, Level 16, State 1, Procedure CheckOptionTest3, Line 6
    Invalid object name 'CheckOptionTest4'.
    יש מצב שבפונקציות כבר אין בעיה אלא רק ב-VIEWS?
    אבל בכל מקרה הדוגמאות האלו ממחישות בהעיות אפשריות.

    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 14:31
  • בשביל להשלים את הדוגמא, הנה יצירת טבלה לדוגמא:

    CREATE TABLE StamTable

    (

    StamTableId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,

    StamTableStr nvarchar(50) NULL

    )


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 14:33
  • את הטבלה אתה מייצר לפני הסקריפטים מעל אני מניח. נכון?
    אחרת כבר ב CASE 2 יש שגיאה
    וכמו כן חסר שדה בטבלה אחרת שוב תקבל שיאה במקרה 2 כבר:
    Invalid column name 'colIntA'

    נקודה נוספת: דיברת על פונקציות ואתה מראה דוגמה על VIEW

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

    * במקרה של VIEW אולי כדאי באמת לבדוק אם יש הגדרת SET שמבטלת את הדבר אבל לא נראה כי זה מהות של VIEW. להציג נתונים קיימים. אפשר לעקוף את הבעיה אולי אם תספר רקע של למה אתה צריך את זה

    אפשר למשל את כל התהליך לבצע דרך פונקציה או אפליקציה חיצונית.

    לוגיקה לפתרון של בניית האלמנטים החסרים:

    תכין פונקציה עבור בנייה של כל אחד מהאלמנטים, שתעבוד בצורה דינאמית. תנסה כמו שדיברנו מעל לבצע את הבנייה של האלמנט בבלוק TRY. בבלוק CATCHשל כל פונקציה תפעיל פונקציה של בניית האלמנט שהיה חסר ואז שוב תפעיל את הפונקציה הנוכחית (כמו שעובדים בהירארכיה שפונקציה מריצה את עצמה).

    * בסופו של דבר ה VIEW יהיה חייב להיבנות אחרי שכל האלמנטים שלו בנויים להערכתי

    יום שלישי 30 אוגוסט 2011 15:30
    מנחה דיון
  • לגבי ההערות על הטבלה: היא אכן מורצת קודם, ואכן שכחתי שדה. סליחה.

    כמו כן, אני אדייק יותר, הסקריפט של הרצת האובייקטים נראה ככה: בדיקת IF  EXISTS + DROP, ויצירה של האובייקט ב-DYNAMIC SQL.

    לדוגמא:

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[foo]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))

    DROP FUNCTION [dbo].[foo]

    GO

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[foo]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))

    BEGIN

    execute dbo.sp_executesql @statement = N'CREATE FUNCTION [dbo].[foo]

    (

    @bar INT

    )

    RETURNS INT

    AS

    BEGIN

    RETURN (SELECT dbo.splunge(@bar));

    END

     

    לגבי פונקציות:

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

    לגבי VIEWS:

    אני לא מצאתי הגדרת SET שתגאל אותי , לפחות לא בינתיים. אבל אם רק VIEWS בעייתיים אז זה פחות נורא - כי המצב ש-VIEW קורא לפונקציה הוא נדיר - גם בכלל וגם אצלי.

    אז מה שחשבתי זה שלפני כל VIEW אני אבדוק האם קיימים האובייקטים שהוא קורא להם, ואם לא אני איצור אותם פיקטיבית, ובהרצה שלהם הם יוסרו (כאמור, אני מבצע בדיקת IF  EXISTS + DROP) ואז ייווצרו מחדש כראוי.


    itaigitt, http://copypastenet.blogspot.com
    יום שלישי 30 אוגוסט 2011 16:02
  • מה שמעניין ומעט אבסורדי זה שניתן למחוק אלמנטים בהם תלוי ה VIEW, אבל ביצירה שלו מתקבלת שגיאה אם הם לא קיימים.

    כך שאכן תמיד אפשר לבנות את האלמנטים בצורה זמנית -> ליצור את ה VIEW -> למחוק את האלמנטים הסמניים -> ליצור אלמנטים אמיתיים לפני ההרצה של ה VIEW או כל שימוש בו (או שמתקבלת שגיאה בנקודה זו)

    נראה לי שזה הפתרון כרגע אכן

    * לגבי הבדיקה אני ממליץ לך לבצע אותה עם בלוק TRY ולא עם תנאי מהסיבה הפשוטה שבלוק TRY יבצע את כל הבדיקות לגבי הצלחה בעוד בשטית IF אתה צריך לחשוב על כל הנתונים לבד ותמיד יכול להיות בעיה נוספת שלא חשבת עליה כמו למשל שהאובייקט טבלה למשל קיים אבל שדה מסויים שנחוץ לא קיים (בתוםך הבלוק TRY אפשר לבדוק עם IF אם רוצים)

    אני מניח שהנושא סגור אם כן :-)
    זמן טוב לעבור לאכול..

    • סומן כתשובה על-ידי itaigitt יום רביעי 31 אוגוסט 2011 06:22
    יום שלישי 30 אוגוסט 2011 16:45
    מנחה דיון
  • היי,

    אשמח אם תוכל/י לעדכן אותנו בסטטוס השאלה שלך.

     

    במידה וקיבלת תשובה מתאימה לשאלתך, יש לסמן את התשובה המתאימה ע"י לחיצה על "סמן כתשובה" ליד סימון ה V הירוק

    אם לא קיבלת תשובה, מומלץ לספק פרטים נוספים אודות הבעיה, פרטי לוג, צילומי מסך וכו'

    על מנת להעלות תמונה לפורום ניתן להעזר במדריך להעלאת תמונה.


    אם תגובתי פתרה את בעייתך - לחץ/י, על "סמן כתשובה" ליד סימן ה V הירוק.

    על מנת להעלות תמונה לפורום ניתן להעזר במדריך להעלאת תמונה
    מיקרוסופט מציעה שירות זה ללא תשלום, למטרת סיוע למשתמשים והעשרת הידע הקשור בטכנולוגיות ובמוצרים של Microsoft. תוכן זה מתפרסם כפי שהוא והוא אינו מעיד על כל אחריות מצד מיקרוסופט.
    יום רביעי 31 אוגוסט 2011 06:55
  • מאיר, עדכנתי וסימנתי תשובות ותגובות מועילות.....

    יכול להיות שלא רואים את זה?


    itaigitt, http://copypastenet.blogspot.com
    יום רביעי 31 אוגוסט 2011 07:00
  • רואים יופי יופי אל דאגה :-)


    אם תגובתי פתרה את בעייתך - לחץ/י, על "סמן כתשובה" ליד סימן ה V הירוק.

    על מנת להעלות תמונה לפורום ניתן להעזר במדריך להעלאת תמונה
    מיקרוסופט מציעה שירות זה ללא תשלום, למטרת סיוע למשתמשים והעשרת הידע הקשור בטכנולוגיות ובמוצרים של Microsoft. תוכן זה מתפרסם כפי שהוא והוא אינו מעיד על כל אחריות מצד מיקרוסופט.
    יום רביעי 31 אוגוסט 2011 07:12