iT邦幫忙

1

SQL where條件如何同時判斷空值或是字串

  • 分享至 

  • xImage

第一次詢問,若表達的不好,非常抱歉。

大家好,最近在調整Trigger遇到些問題
目前狀況是,當某張表有做修改或新增
Trigger會自動寫入log
但因為這張表會頻繁的做全刪再全增的動作
導致大量的相同資料會一直存進log

需求是希望做到在存進log時先判斷如果欄位沒變就別新增
做法是先select log表裡最新的資料判斷欄位有沒有變
如果select出的表有值就代表有一樣的資料所以不新增,沒有值就新增。

目前遇到的問題是,這張表的欄位有可能是null

我的語法如下
select * from logTable
where 欄位=表的欄位變數

這個變數如果輸入null值
select * from logTable
where 欄位=null

就會select不出東西,導致就算資料沒變還是會寫進log

目前知道null的話得用 is null判斷
但偏偏欄位有可能是字串

請問在sql要如何達成這樣的寫法呢?
先判斷表的欄位變數是null的話
使用 where 欄位is null
欄位變數是字串的話
使用 where 欄位 =變數

或是有更好的辦法可以提供,謝謝

BeEvil_Y iT邦新手 4 級 ‧ 2021-10-06 14:47:53 檢舉
你好喔
我其實沒有接觸SQL

但我現在覺得你問的這個東西,很奇怪。
你現在說的 select * from where like and or 是資料庫的查詢語法。

但是你提的Trigger 是別的東西。
是「獨立」於資料庫、查詢語法以外的東西。

他可以寫在前端( Javascript )預先判斷
會寫在後端 (PHP、Asp.net) 送出Http封包前判斷

也可以寫在資料庫裡面(看你是用哪一個)


你知道為什麼我會覺得奇怪?
雖然我沒摸過SQL

但是Select 是查詢是GET,是從資料庫調東西。

你的Trigger是發生在更新、刪除、改變的時候。

你怎麼會去追縱Select?
你應該是去追縱delete、update、insert才對。

問題來了
如果你要去追別人都搜你資料庫的什麼(select)
那是不是代表,就算欄位是NULL值,你也要記錄起來。

因為你這張trigger表就是針對連線安全追縱設的
不是資料表變動追縱設的

這是其中一回事喔

你trigger表寫進LOG,也是利用insert語法寫在觸發區。

不管你有沒有寫進LOG,還是有觸發Trigger。因為你是利用資料庫再過濾。


如果你不想寫進LOG
那你用IF判斷來控制不就好了?

如果 XXXX 不是 NULL
Insert LOG
其它
.....
結束

所以你SQL的Trigger寫在哪裡?
你的寫進LOG在第幾行?
你要怎麼用IF包起來?
你是在追縱Select?
你這個Trigger是在追縱資料變動,還是連線記錄?
你到底再問什麼?

機車呢,打字到一半當機。
我不想再重打了。

直接跳重點

你如果要利用Select寫進Trigger來判斷是不是有相同資料。

先在Trigger宣告一個變數
把你所有進來的筆數寫進陣列放在這個變數裡

計算這個陣列有幾筆

再利用迴圈逐筆去對你設在Trigger裡的Select。

如果沒有一樣的,寫進LOG,中斷迴圈。

這樣就不會讓你的LOG又臭又長。
代價是很吃你的CPU。

你們是哪個行業的?我記得~ 在前後端很忌諱資料庫一次更新多筆資料?

你如果一次要更新多筆資料。
你們為什麼不利用前後端。
把所有的資料打包封成陣列。

舉例:(三筆)
1、路人甲、100、2021/10/06
2、路人乙、200、2021/10/06
3、路人丁、300、2021/10/06

變成:(一筆)
1、(路人甲,100),(路人甲,200),(路人甲,300)、2021/10/06

然後你們前後端用Select在Get資料時,再去拆array,分裝在界面?

猜猜看?
你這樣玩,還可以挑時段寫語法,讓伺服器在離峰期拆Array寫到其它表裡。

Google就是這樣玩的
他們就是一整串包起來成為array,然後用hash封裝。
一次就一筆。

你們玩遊戲的時候也是這樣弄啊。
存檔時,哪有分什麼很多資料表來存?
就一串一堆逗號分隔的資料,hash加密存起來。

你這個問題可能涉及「重構」,我覺得。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
純真的人
iT邦大師 1 級 ‧ 2021-10-01 09:26:39
最佳解答

統一空字串比對~

declare @Str nvarchar(50) = null

select * 
from logTable
where isNull(欄位,'') = isNull(@Str,'')
3
小魚
iT邦大師 1 級 ‧ 2021-10-01 08:59:47

= null 改成 IS NULL
<> null 要用 IS NOT NULL
如果還有其他條件就看情況用 OR 或是 AND

譬如這樣

SELECT xxx FROM ooo WHERE `name` IS NULL OR `name` = '';

之類的.

IN沒有試過,
不確定可不可以,
感覺可能是不行.

1
asd3733653
iT邦新手 2 級 ‧ 2021-10-01 09:20:10

如果需求是這樣,我是會這樣寫

WHERE ISNULL([欄位],'@@@@') = ISNULL('搜尋值', '@@@@')

'@@@@' 可以替換 概念是這樣

寫的不好,還請指點指點/images/emoticon/emoticon39.gif

0
bsexp301479
iT邦新手 3 級 ‧ 2021-10-01 11:03:45
SELECT * 
FROM logTable
WHERE ISNULL('更新欄位','') <> ''
AND ISNULL(欄位,'') <> ISNULL('更新欄位','')
0
Luke
iT邦研究生 5 級 ‧ 2021-10-01 11:14:34
INSERT INTO logTable
SELECT xxx,xxx,xxx,xxx FROM logTable WHERE NOT EXSIT (select 1 from logTable where isNull([欄位],'') = isNull(@Str,''))

NOT EXSIT 大致上是說不存在 ,才 INSERT
所以,您可以使用值存不存在,就知道是否變更了
值在=>表示沒有變更
值不在=>表示有變更

另外 isNull([欄位],'') ==>SQL Server
NVL([欄位],'') ==> Oracle
至於My SQL 、MongoDB、pgAdmin ...
不是很清楚~

Trigger==>會影響原本的表格INSERT、UPDATE、DELETE 速度(量大的時候)

0
小山丘
iT邦新手 2 級 ‧ 2021-10-01 14:28:46

有試過用MERGE語法嗎
這樣就可以不用全刪再全增了
大概是這樣

MERGE INTO   #TEMP1   --要新增修改的表
      USING  #TEMP2   --參考的表
      ON     #TEMP1.欄位 = #TEMP2.欄位   --條件         
WHEN  MATCHED   THEN   --當條件符合時
      UPDATE  SET   #TEMP1.欄位=#TEMP2.欄位
WHEN  NOT MATCHED  THEN   --條件不符合時
      INSERT VALUE(#TEMP2.欄位)

然後NULL或空字串則是用ISNULL判斷
ISNULL(欄位,'')=''

可以搜尋一些文章看看
https://docs.microsoft.com/zh-tw/sql/t-sql/statements/merge-transact-sql?view=sql-server-ver15

0
karakamin
iT邦新手 3 級 ‧ 2021-10-01 23:29:35

不確定你的資料庫是哪一種
以 MS SQL為例

SELECT *
FROM TABLE
WHERE COALESCE(欄位,'') = ''

DOCS 上有更多用法
COALESCE (Transact-SQL)

我要發表回答

立即登入回答