iT邦幫忙

1

SQL 能不能用子搜尋結果找到另一個已經存在的 Table 當作 Select 來源?

不好意思標題可能不太好理解 …
問題的原始需求,我要從已存在的多個 Table 中去查詢資料
但我要先去查一個關聯表才知道該去查哪個 Table

不管是 SQL 或 MySQL,如果我下一個語法像這樣
SELECT   *
FROM (
SELECT   TableName
FROM   TableList
WHERE   Condition = 'target'
)

若目前已存在的 Table 有 A01,B01,C01
假設我查完會得到 A01 ,可以把 A01 當成 FROM 後面的目標並指向已存在的 A01 Table嗎?
我要先靠子查詢找到符合指定條件的 Table 名稱才去查那個 Table
只靠 T-SQL 的語法辦的到嗎?

--Edit 12/05 17:03
應該是我問題描述的不夠清楚 ..

現在 DB : Test 中有 4 個 Table

  1. TableRef
TableName Type
A01 M001
A01 M002
B01 M003
C01 M004
  1. A01
ID Value
1 11
2 12
3 13
4 14
  1. B01
  2. C01

B01 跟 C01 構造類似 A01 ,但field內容不一樣
TableName 有數十個,Type 有數百種
但我要查資料時只會得到 Type ,要靠 Type 才能知道要查哪一個 Table

我原本是想要靠一行指令就完成這個查詢…
例如
select * from (select TableName from TableRef where type = 'M137')
但這樣行不通…

目前參考 allenlwh 的回答再 google 後是用以下的方式做到類似的結果
SET @select_test = CONCAT('SELECT * FROM ',
(SELECT GROUP_CONCAT(TableName) FROM TableRef where Type = 'm01')
);
PREPARE pr FROM @select_test;
EXECUTE pr;

實際的應用環境是 mysql 跟 c#
但這個模式不知道怎麼套用到C# MySql.Data.MySqlClient .Net Core Class Library
x_x

allenlwh iT邦研究生 5 級 ‧ 2018-12-06 08:35:05 檢舉
我說的是"sp_executesql",不是EXECUTE
我有注意到,但 mysql 中沒有 sp_executesql ,但看起來一樣可以得到結果
所以在 sqlserver 中 sp_executesql 跟 execute 是不一樣的功能嗎?
自己補充 .. 我最後的問題, ADO.NET 不能這樣搞
在 ADO.NET 中 subquery 不能當成 parameter ..
看理由是跟防範 SQL Injection 有關
2
allenlwh
iT邦研究生 5 級 ‧ 2018-12-05 10:51:55
最佳解答

你可以先把查出來的TableName組合成另一個T-SQL語法,全部都查完後,利用sp_executesql再一併做查詢。
請參考:
sp_executesql (Transact-SQL)
https://docs.microsoft.com/zh-tw/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-2017

謝謝你的回答,參考你的回答後我有找到我要的答案了
雖然又碰到新的問題 XD

1
純真的人
iT邦高手 3 級 ‧ 2018-12-05 10:31:20

T-SQL可以~
你先把查到的結果,先丟到暫存資料表~再把暫存資料表反查原來的資料表~

Declare @A01 table(
....
)

insert into @A01
select .... from 來源資料表

select *
from 來源資料表
where (
    @A01 .....
)

謝謝你的回答,但可能是我問題描述不清楚,看不懂你的回答..
我有更新發問內容,如果可以的話請再幫我看一下 @@..

嗯嗯~你的問題~allenlwh已經幫你答出來了~
至於後續問題@@...

你是說使用mysql資料庫~
那也是一樣的用法~
是指這個吧?
https://ithelp.ithome.com.tw/articles/10198629

SET @Sql = 'SQL語句';
PREPARE test from @Sql;
execute test;

謝謝你 ~ 在 mysql 的應用是成功了
只是要從 C# 套用這個 statement 會失敗,還不確定為什麼
我用的那個套件應該算是 mysql 版的 ADO.NET (我也不知道這樣稱呼對不對?)
看起來在套件設定 parameter 不能設成 subquery,還要再試試看

另外從你的文章裡又學到全庫全表搜尋,感謝

2
dennis124599
iT邦新手 5 級 ‧ 2018-12-05 11:08:47

declare @a nvarchar(50)
declare @b nvarchar(50)
set @a = (
SELECT *FROM
(SELECT TableName
FROM TableList
WHERE Condition = 'target')
)
set @b = ('select * from '+@a)
exec (@b)

看更多先前的回應...收起先前的回應...

謝謝你的回答,我後來找到的解答很類似這個模式
但直接複製你的回答不管是 sql 或 mysql 好像都會出錯 @@

我的環境是MSSQL2017
拍謝剛剛發現SET @a 那裡貼錯了
改成
set @a = (
SELECT TableName
FROM TableList
WHERE Condition = 'target'
)
原本的應該是
set @a = (
SELECT *FROM
(SELECT TableName
FROM TableList
WHERE Condition = 'target') a
)

allenlwh iT邦研究生 5 級 ‧ 2018-12-06 08:49:30 檢舉
Table[ProjCode]
    idx	ProjCode	ProjName
    2	A001	    ProjA001
    3	B001	    ProjB001
    4	C001	    ProjC001
    5	D001	    ProjD001
Table[EmpProjList]
    idx	EmpID	            ProjCode
    7	administrator_A001	A001
    8	administrator_B001	B001
    9	administrator_C001	C001
declare @sqlcmd nvarchar(max)
declare @projecode varchar(10)

select @projecode=ProjCode from [ProjCode]
where ProjName='projb001'

set @sqlcmd='select * from EmpProjList where ProjCode='''+@projecode+''''

 EXECUTE sp_executesql @sqlcmd

結果

idx	EmpID	            ProjCode
8	administrator_B001	B001

dennis124599 不好意思我覺得可能是我的 navicat 版本太舊所以才會跳 error ,說不定你本來的語法是對的,我裝個 SSMS 來試看看

allenlwh 謝謝你精美的解說 @A@
我後來用在 mysql 的解決方法就是類似你提供的內容
主要是差在變數放的位置,你提供的是放在where的條件
我需要的是放在 from 的 table 名稱

set @sqlcmd = 'select * from @projecode'

我想了一下應該是這個問題本來就很奇怪,然後解釋的不夠清楚
最主要的問題是我不知道要去查哪個 table
但 subquery return 的結果不能指向一個已經存在的 table
所以要靠變數把 sqlcmd 組合成我要的命令
再用 sp_executesql 來執行

但資料庫設計上不知道要去查哪個 table 似乎是不正常的設計方式

dennis124599 剛測試了,真的是我的 navicat 版本問題,你提供的兩種語法在 ssms 都是可行的,謝謝 :D

0
simon0627
iT邦新手 2 級 ‧ 2018-12-06 13:49:36

SELECT a.name FROM (SELECT name FROM agentinformation) a
感覺你要的是這個?

看更多先前的回應...收起先前的回應...

謝謝你的回答,但感覺不一樣 @@

simon0627 iT邦新手 2 級 ‧ 2018-12-06 15:14:39 檢舉

select * from (select TableName from TableRef where type = 'M137') A

select TableName from TableRef where type = 'M137'

select * from (select TableName from TableRef where type = 'M137') A

這兩個語句 select 出來結果是一樣的喔

TableName
A01

雖然我有一個 table 名字叫 A01
但這個語法的結果並不會去搜尋 A01 這個 table

simon0627 iT邦新手 2 級 ‧ 2018-12-06 16:43:18 檢舉

嗯看懂你的問題了 XD 感謝分享

我要發表回答

立即登入回答