トップ回答者
リンクサーバーを使用したときに、CASE文でエラーになる

質問
-
SQL Server 2005 Express から、 SQL Server 2000 へ向けて、リンクサーバーを設定しています。
SQL Server 2005 Express 上で、以下のようなSQL文を流すと、
「ステートメントを準備できませんでした。」「Case 式は、10 レベルまでしかネストできません。」
とエラーメッセージが出てしまいます。DECLARE @aaa Integer
SET @aaa = 1
SELECT
CASE WHEN @aaa = 1 THEN 'a'
WHEN @aaa = 2 THEN 'b'
WHEN @aaa = 3 THEN 'c'
WHEN @aaa = 4 THEN 'd'
WHEN @aaa = 5 THEN 'e'
WHEN @aaa = 6 THEN 'f'
WHEN @aaa = 7 THEN 'g'
WHEN @aaa = 8 THEN 'h'
WHEN @aaa = 9 THEN 'i'
WHEN @aaa = 10 THEN 'j'
WHEN @aaa = 11 THEN 'k'
ELSE '' END
FROM [リンクサーバーIP].DB名.dbo.テーブル名当然、リンクサーバー経由せず、普通に実行すると問題ないです。
もう SQL Server 2000 もサポート切れですし、SQL Server 2012 から SQL Server 2000 にリンクサーバーが貼れないようなので、
半分別の手法を模索中ですが、代替え案等がございましたら、あわせて教えていただければと思います。
回答
-
ただ、リンクサーバーだと、CASE文をネストしたわけでもないのに、ネストエラーが出るのが解せないですね。。。
あまり深く考えず、この件は解決といたします。不思議な現象で興味があったので調べてみました。正しいかどうかは別として、以下が参考になりました。
Why do linked servers have a limitation of 10 branches in a CASE expression?
http://dba.stackexchange.com/questions/42837/why-do-linked-servers-have-a-limitation-of-10-branches-in-a-case-expression簡単に意訳すれば、パーサーがcase文をネストした文を生成し、それをリンクサーバーに送るからのようです。ローカルではこの生成した文を使わないので問題が発生しないとのことです。
#追記。言い忘れました。上のページに最後に解決策らしきものが書いてありますね。裏技っぽいですが・・・
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 nagino - 引退エンジニア 2014年5月21日 6:01
- 編集済み trapemiya 2014年5月21日 6:11 誤記訂正。「買い忘れ」→「言い忘れ」
- 回答としてマーク ねむねむ 2014年5月21日 6:20
すべての返信
-
提示されている要件を実現するだけであれば例えば以下のような様々な手法が考えられますが、それが使えないから CASE 文で 1 つ 1 つ分岐しているという状況でしょうか?
--方法1
DECLARE @aaa Integer
SET @aaa = 1
SELECT
CASE WHEN 1 <= @aaa AND @aaa <= 11 THEN CHAR(@aaa + 96)
ELSE '' END
FROM [リンクサーバーIP].DB名.dbo.テーブル名
--方法2
DECLARE @aaa Integer
SET @aaa = 1
SELECT 'a' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 1
UNION ALL
SELECT 'b' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 2
UNION ALL
SELECT 'c' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 3
UNION ALL
SELECT 'd' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 4
UNION ALL
SELECT 'e' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 5
UNION ALL
SELECT 'f' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 6
UNION ALL
SELECT 'g' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 7
UNION ALL
SELECT 'h' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 8
UNION ALL
SELECT 'i' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 9
UNION ALL
SELECT 'j' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 10
UNION ALL
SELECT 'k' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa = 11
UNION ALL
SELECT '' FROM [リンクサーバーIP].DB名.dbo.テーブル名 WHERE @aaa < 1 OR 11 < @aaa
MCITP(Database Developer/Database Administrator)
- 編集済み nagino - 引退エンジニア 2014年5月21日 2:08
- 回答としてマーク ねむねむ 2014年5月21日 2:25
- 回答としてマークされていない ねむねむ 2014年5月21日 6:20
-
あー、それはエラーメッセージが誤解しやすい表現になっているだけです。
WHEN 句(ELSE 句を含むかどうかは失念しました)が 11 個以上あるとそのエラーになったはずです。
WHEN 句を減らしていくとエラーが出なくなるはずです。
ご参考まで。
MCITP(Database Developer/Database Administrator)
- 編集済み nagino - 引退エンジニア 2014年5月21日 2:57
-
本件の解決とは関係無い上、提示されたクエリは例としてあげただけとの事ですがcase文は
DECLARE @aaa Integer SET @aaa = 1 SELECT CASE @aaa WHEN 1 THEN 'a' WHEN 2 THEN 'b' WHEN 3 THEN 'c' WHEN 4 THEN 'd' WHEN 5 THEN 'e' WHEN 6 THEN 'f' WHEN 7 THEN 'g' WHEN 8 THEN 'h' WHEN 9 THEN 'i' WHEN 10 THEN 'j' WHEN 11 THEN 'k' ELSE '' END FROM [リンクサーバーIP].DB名.dbo.テーブル名
こんな書き方の方が私は好きです。
-
ただ、リンクサーバーだと、CASE文をネストしたわけでもないのに、ネストエラーが出るのが解せないですね。。。
あまり深く考えず、この件は解決といたします。不思議な現象で興味があったので調べてみました。正しいかどうかは別として、以下が参考になりました。
Why do linked servers have a limitation of 10 branches in a CASE expression?
http://dba.stackexchange.com/questions/42837/why-do-linked-servers-have-a-limitation-of-10-branches-in-a-case-expression簡単に意訳すれば、パーサーがcase文をネストした文を生成し、それをリンクサーバーに送るからのようです。ローカルではこの生成した文を使わないので問題が発生しないとのことです。
#追記。言い忘れました。上のページに最後に解決策らしきものが書いてありますね。裏技っぽいですが・・・
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 nagino - 引退エンジニア 2014年5月21日 6:01
- 編集済み trapemiya 2014年5月21日 6:11 誤記訂正。「買い忘れ」→「言い忘れ」
- 回答としてマーク ねむねむ 2014年5月21日 6:20