Sql-Server

為什麼我的數據庫結構和 SELECT 操作會生成 NULL?

  • September 6, 2017

我對數據庫問題沒有太多經驗,所以請原諒文字牆,我相信上下文對於理解問題和目標很重要。


我每天都從另一個系統收到一個 CSV 文件,我希望將其保留在 Microsoft SQL Server 上執行的數據庫中。為此,我每天安排一個 PowerShell 腳本,該腳本使用 bcp 實用程序將 CSV ( accounts.csvaccounts_stage )“載入”到具有 CSV 文件“精確”佈局的表 ( ) 中。此外,我將時間戳“寫入”到另一個表 ( import_stage) 中。該accounts_stage表有一個觸發器集,並且 bcp 被配置為觸發該觸發器。

導入完成後,我想“規範化”數據。對於一個基本範例,假設這僅涉及契約編號(在 CSV 文件中名為“Vnr”的欄位),它是一個字元串。我有另一個表 ( contracts),它被觸發器填充:

INSERT INTO dzp.contractid(vnr)
SELECT DISTINCT
   a.Vnr
FROM dzp.accounts_stage a
WHERE NOT EXISTS(
   SELECT id.vnr
   FROM dzp.contractid id
)

這應該並且似乎可以完成,添加曾經導入到表中的所有契約編號contractidscontractids.contractId是 BIGINT PRIMARY KEY、IDENTITY 和自動增量。

我將導入元數據添加到我的表中,如下所示:

  CREATE TABLE #IMPORTMETADATA
           ([importid] bigint
           ,[generated_timestamp] datetime
           ,[imported_timestamp] datetime
           )
   INSERT INTO #IMPORTMETADATA
       SELECT TOP 1 [importid], [timestamp_import], [generated_timestamp]         
   FROM
           [QGTAA].[dzp].[import]
       ORDER BY
           [timestamp_import] DESC

接下來,觸發器應該插入數據 FROM accounts_stageINTO accounts,以便contractId替換(從原始字元串表示到contracts表的 PRIMARY KEY)。

INSERT INTO [dzp].[accounts]
     ([Udnr]
     ,[ContractId]
     -- snip
     ,[generated_timestamp]
     ,[importid]
     )
SELECT 
   a.[Udnr], 
   cid.contractId, 
   -- snip
   meta.[generated_timestamp], 
   meta.[importid]
FROM [QGTAA].[dzp].[accounts_stage] a
LEFT JOIN dzp.contractid cid ON cid.vnr = a.Vnr
CROSS JOIN #IMPORTMETADATA meta

但是,這最後一步失敗了,因為最後一個塊中的 SELECT 操作產生了contractIdIS NULL 的行,這是我沒有預料到的。現在我認為問題出在 LEFT JOIN 的某個地方,但我不確定為什麼。

問題

  1. 有人可以在這個特定問題上為我指出正確的方向嗎?
  2. 我對數據庫沒有太多經驗,這甚至是一種實現我想要的理智的方式,還是一種完全瘋狂的方式?有沒有更好的辦法?

謝謝!

你的第一個有問題NOT EXISTS。讓我們看一下您目前的查詢:

INSERT INTO dzp.contractid(vnr)
SELECT DISTINCT
   a.Vnr
FROM dzp.accounts_stage a
WHERE NOT EXISTS(
   SELECT id.vnr
   FROM dzp.contractid id
)

因此,這裡發生的情況是NOT EXISTS,您正在使用的dzp.contractid表為空時才會返回 true。一旦它有一行(或更多),NOT EXISTS就會返回false主表的每一行,因為SELECT id.vnr FROM dzp.contractid有一個結果集,並且您最終會在表中插入重複的值。

您需要做的是將此子查詢與主表相關聯:

INSERT INTO dzp.contractid(vnr)
SELECT DISTINCT
   a.Vnr
FROM dzp.accounts_stage a
WHERE NOT EXISTS(
   SELECT id.vnr
   FROM dzp.contractid id
   WHERE id.vnr = a.vnr
);

此外,CROSS JOIN最新導入的數據對我來說沒有多大意義,而且您沒有檢查數據是否已存在於accounts表中的事實也沒有。

引用自:https://dba.stackexchange.com/questions/185221