2017-04-07 9 views
0

硬編碼,這個工程:此SQL服務器查詢是否存在語法錯誤?我可以不使用「目標。@ 1」嗎?

var insertCommand1 = ("MERGE INTO Leaderboard WITH (HOLDLOCK) AS target USING (SELECT * FROM Scores WHERE WeekNumber = 7) AS Source ON (target.id = source.id) WHEN MATCHED THEN UPDATE SET target.Id = source.Id, target.Week7 = source.weeklyScore WHEN NOT MATCHED THEN INSERT (Id, Week7) VALUES (source.Id, source.weeklyScore);"); 

db.Execute(insertCommand1); 

這不起作用:

var insertCommand1 = ("MERGE INTO Leaderboard WITH (HOLDLOCK) AS target USING (SELECT * FROM Scores WHERE WeekNumber = @0) AS Source ON (target.id = source.id) WHEN MATCHED THEN UPDATE SET target.Id = source.Id, [email protected] = source.weeklyScore WHEN NOT MATCHED THEN INSERT (Id, @2) VALUES (source.Id, source.weeklyScore);"); 

db.Execute(insertCommand1, weeknum, weekstring, weekstring); 

錯誤說,有近一個語法錯誤@ 1。這可能是什麼? 我已經調試過,以確保weeknum和weekstring的值是正確的。

在SQL服務器2015年VS

模式工作的2表 -

Leaderboard(Id, Week1, Week2, Week3, Week4, Week5, 
       Week6, Week7, Week8, Week9, Week10) 
with Id as the primary key 

Scores(Id, WeekNumber, weeklyScore) 
with Id and WeekNumber as the primary key 
+0

您可能會問錯的問題[**什麼是XY問題?**](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) 向我們顯示一些數據和預期的輸出以及您想要達到的目標,我們可以爲您提供更多幫助。 –

+0

@JuanCarlosOropeza剛剛發佈了模式 - 希望這有助於! –

+0

Jules你的模型看起來應該正常化,'排行榜'應該是'{Id,Week_id,Score}'然後如果你想顯示幾個星期你使用'PIVOT'這將允許你添加刪除周而不改變你的數據庫設計。 –

回答

2

您正在試圖設置使用參數字段名,並@參數是值的。

, [email protected] = source.weeklyScore 

應該

, target.something = @1 
+0

噢好吧。這有什麼替代方法?這是一個變化的動態變量,我需要能夠更改查詢所說的內容 –

+0

您可以改爲創建動態查詢。但是再次不確定你想在這裏實現什麼。首先看你的查詢看起來不合邏輯,所以我們需要db schema樣本數據和慾望輸出來理解你需要的東西。 –

+0

您必須將字符串版本中的@ 1替換爲正在檢查的字段的名稱,例如var insertCommand1 =(「MERGE INTO Leaderboard WITH(HOLDLOCK)AS target USING(SELECT * FROM Scores WHERE WeekNumber = @ 0)AS Source ON(target.id = source.id)WHEN MATCHED UPDATE SET target.Id = source。 Id,target。「&fieldNameVar&」= source.weeklyScore WHEN NOT MATCHED THEN INSERT(Id,@ 2)VALUES(source.Id,source.weeklyScore);「);' –

1

它看起來就像你試圖用一個參數作爲一個架構對象名稱,而不是一個值。正如你所發現的,這不起作用。參數僅用於值。

如果你需要一個動態架構對象名稱,要注意兩件事情:

  1. 它可以通過多影響性能,雖然可能不是。
  2. SQL注入是一個重要問題。

如果問題成爲問題,您可以衡量的第一個問題,但我懷疑它會如何。第二個可以小心處理。使用SQL注入的簡單規則並不是總是爲所有內容使用參數,但決不會將用戶修改的值作爲代碼執行。

對於模式對象,您已經有了一組有限的可能值。所以你可以在你的代碼中建立一個已知值的列表。這不是用戶修改的,所以它是安全的。 (也許它是硬編碼的,也許你從數據庫模式自動生成它,這取決於你自己。)

使用變量,檢查它是否與列表中的值匹配。如果沒有,那是錯誤的,代碼應該簡單地引發適當的異常或以其他方式處理該錯誤情況。如果匹配,從安全的非用戶可修改的值的已知的有限列表,請使用您的查詢從列表中匹配值的元素:

var query = string.Format("SELECT SomeTable.{0} FROM SomeTable ...", knownList[x]); 

(或者無論你想構建它,希望你這個想法)。

然後用這個動態生成的查詢,你可以添加你的參數值,你就全部設置了。

+0

我不知道如何影響sql性能,只是在發送到數據庫之前創建一個字符串。但是,處理有效輸入的'knowList'以避免sql注入的好方法。 –

+0

@JuanCarlosOropeza:它*可能*不會影響性能,如果是這樣,可以忽略不計。我正在思考各種系統在播放緩存查詢和執行計劃以及動態構建的字符串是否會影響到這一點。我不能保證它不會。 – David