Home
%3CLINGO-SUB%20id%3D%22lingo-sub-386226%22%20slang%3D%22en-US%22%3EPublic%20Preview%20of%20MATCH%20support%20in%20MERGE%20DML%20for%20Graph%20tables%20in%20Azure%20SQL%20Database%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-386226%22%20slang%3D%22en-US%22%3E%0A%20%26lt%3Bmeta%20http-equiv%3D%22Content-Type%22%20content%3D%22text%2Fhtml%3B%20charset%3DUTF-8%22%20%2F%26gt%3B%3CSTRONG%3EFirst%20published%20on%20MSDN%20on%20Jul%2016%2C%202018%20%3C%2FSTRONG%3E%20%3CBR%20%2F%3E%20SQL%20Server%202017%20and%20Azure%20SQL%20Database%20introduced%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fsql%2Frelational-databases%2Fgraphs%2Fsql-graph-overview%3Fview%3Dsql-server-2017%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20native%20graph%20database%20capabilities%20%3C%2FA%3E%20used%20to%20model%20many-to-many%20relationships.%20The%20first%20implementation%20of%20SQL%20Graph%20introduced%20support%20for%20edges%20to%20represent%20relationships%2C%20nodes%20to%20represent%20entities%20and%20a%20new%20MATCH%20predicate%20to%20support%20graph%20pattern%20matching%20and%20traversal.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20We%20will%20be%20further%20expanding%20the%20graph%20database%20capabilities%20with%20several%20new%20features.%20In%20this%20blog%20we%20will%20discuss%20one%20of%20these%20features%20that%20is%20now%20available%20for%20public%20preview%20in%20Azure%20SQL%20Database%2C%20%3CSTRONG%3E%20MATCH%20support%20in%20MERGE%20DML%20for%20graph%20tables%20%3C%2FSTRONG%3E%20.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20The%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fsql%2Ft-sql%2Fstatements%2Fmerge-transact-sql%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20MERGE%20%3C%2FA%3E%20statement%20performs%20insert%2C%20update%2C%20or%20delete%20operations%20on%20a%20target%20table%20based%20on%20the%20results%20of%20a%20join%20with%20a%20source%20table.%20For%20example%2C%20you%20can%20synchronize%20two%20tables%20by%20inserting%2C%20updating%2C%20or%20deleting%20rows%20in%20a%20target%20table%20based%20on%20differences%20between%20the%20target%20table%20and%20the%20source%20table.%20Using%20MATCH%20predicates%20in%20a%20MERGE%20statement%20is%20now%20supported%20on%20Azure%20SQL%20Database.%20That%20is%2C%20it%20is%20now%20possible%20to%20merge%20your%20current%20graph%20data%20(node%20or%20edge%20tables)%20with%20new%20data%20using%20the%20MATCH%20predicates%20to%20specify%20graph%20relationships%20in%20a%20single%20statement%2C%20instead%20of%20separate%20INSERT%2FUPDATE%2FDELETE%20statements.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20In%20this%20post%20we%20will%20discuss%20few%20examples%20of%20how%20MATCH%20can%20be%20used%20in%20MERGE%20statement.%20For%20these%20examples%2C%20we%20have%20created%20%3CEM%3E%20Customers%20%3C%2FEM%3E%20and%20%3CEM%3E%20StockItems%20%3C%2FEM%3E%20node%20tables%20and%20%3CEM%3E%20bought%20%3C%2FEM%3E%20edge%20table%20in%20the%20%3CEM%3E%20WideWorldImporters%20%3C%2FEM%3E%20database.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F99013i9265880B22299837%22%20%2F%3E%20%3CBR%20%2F%3E%3CP%3E%3CSTRONG%3E%20%3CEM%3E%20Graph%20schema%20for%20MERGE%20examples%3A%20Customers%20bought%20StockItems%20%3C%2FEM%3E%20%3C%2FSTRONG%3E%3C%2FP%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId-1731638303%22%20id%3D%22toc-hId-1763929693%22%3EMerging%20node%20table%20data%3C%2FH2%3E%3CBR%20%2F%3E%20A%20MERGE%20statement%20can%20be%20used%20to%20insert%20a%20new%20node%20record%20or%20update%20attributes%20on%20an%20existing%20record%20using%20a%20single%20statement%20(UPSERT).%20A%20MATCH%20predicate%20is%20not%20necessarily%20required%20for%20this%20scenario%20and%20hence%2C%20using%20merge%20to%20upsert%20node%20data%20was%20supported%20in%20previous%20releases.%20Here%20is%20an%20example%3A%20%3CEM%3E%20WideWorldImporters%20%3C%2FEM%3E%20would%20like%20to%20create%20a%20new%20%3CEM%3E%20Customers%20%3C%2FEM%3E%20node%20record%20when%20a%20customer%20buys%20a%20stockitem.%20If%20the%20customer%20already%20exists%20and%20a%20new%20%3CEM%3E%20WebsiteURL%20%3C%2FEM%3E%20was%20provided%2C%20they%20would%20like%20to%20update%20the%20customer%20record%20with%20the%20new%20information.%20They%20can%20use%20the%20following%20MERGE%20DML%20on%20the%20%3CEM%3E%20Customers%20%3C%2FEM%3E%20node%20table%3A%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22sql%22%5D%20%3CBR%20%2F%3E%20CREATE%20OR%20ALTER%20PROCEDURE%20dbo.mergeCustomerNode%20%3CBR%20%2F%3E%20%40CustomerID%20BIGINT%2C%20%3CBR%20%2F%3E%20%40CustomerName%20VARCHAR(100)%2C%20%3CBR%20%2F%3E%20%40CustomerWebsiteURL%20VARCHAR(1000)%20%3CBR%20%2F%3E%20AS%20%3CBR%20%2F%3E%20BEGIN%20%3CBR%20%2F%3E%20MERGE%20Nodes.Customers%20AS%20C%20%3CBR%20%2F%3E%20USING%20(SELECT%20%40CustomerID%2C%20%40CustomerName%2C%20%40CustomerWebsiteURL)%20%3CBR%20%2F%3E%20AS%20T%20(CustomerID%2C%20CustomerName%2C%20CustomerWebsiteURL)%20%3CBR%20%2F%3E%20ON%20(C.CustomerID%20%3D%20T.CustomerID)%20%3CBR%20%2F%3E%20WHEN%20MATCHED%20THEN%20%3CBR%20%2F%3E%20UPDATE%20SET%20WebsiteURL%20%3D%20T.CustomerWebsiteURL%20%3CBR%20%2F%3E%20WHEN%20NOT%20MATCHED%20THEN%20%3CBR%20%2F%3E%20INSERT%20(CustomerID%2C%20CustomerName%2C%20WebsiteURL)%20%3CBR%20%2F%3E%20VALUES%20(T.CustomerID%2C%20T.CustomerName%2C%20T.CustomerWebsiteURL)%20%3B%20%3CBR%20%2F%3E%20END%20%3CBR%20%2F%3E%20GO%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId--820518658%22%20id%3D%22toc-hId--788227268%22%3EMerging%20edge%20table%20data%3C%2FH2%3E%3CBR%20%2F%3E%20With%20this%20release%2C%20users%20can%20insert%20a%20new%20edge%20record%20or%20update%20or%20delete%20an%20existing%20one%20in%20a%20single%20statement%20using%20the%20MERGE%20DML.%20For%20example%2C%20continuing%20with%20the%20graph%20shown%20above%2C%20the%20following%20MERGE%20DML%20can%20be%20used%20to%20either%20insert%20a%20new%20%3CEM%3E%20bought%20%3C%2FEM%3E%20edge%20when%20a%20%3CEM%3E%20Customer%20%3C%2FEM%3E%20buys%20a%20%3CEM%3E%20StockItem%20%3C%2FEM%3E%20%2C%20or%20if%20the%20edge%20already%20exists%20then%20update%20the%20value%20of%20%3CEM%3E%20PurchasedCount%20%3C%2FEM%3E%20attribute%20on%20the%20existing%20edge%20record%3A%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22sql%22%5D%20%3CBR%20%2F%3E%20CREATE%20PROCEDURE%20dbo.mergeBoughtEdge%20%3CBR%20%2F%3E%20%40CustomerID%20integer%2C%20%3CBR%20%2F%3E%20%40ProductID%20integer%2C%20%3CBR%20%2F%3E%20%40purchased_count%20integer%20%3CBR%20%2F%3E%20AS%20%3CBR%20%2F%3E%20BEGIN%20%3CBR%20%2F%3E%20MERGE%20Edges.bought%20%3CBR%20%2F%3E%20USING%20((SELECT%20%40CustomerID%2C%20%40ProductID)%20AS%20T%20(CustomerID%2C%20ProductID)%20%3CBR%20%2F%3E%20JOIN%20Nodes.Customers%20ON%20T.CustomerID%20%3D%20Customers.CustomerID%20%3CBR%20%2F%3E%20JOIN%20Nodes.StockItems%20ON%20T.ProductID%20%3D%20StockItems.StockItemID)%20%3CBR%20%2F%3E%20ON%20MATCH%20(Customers-(bought)-%26gt%3BStockItems)%20%3CBR%20%2F%3E%20WHEN%20MATCHED%20THEN%20%3CBR%20%2F%3E%20UPDATE%20SET%20PurchasedCount%20%3D%20PurchasedCount%20%2B%20%40purchased_count%20%3CBR%20%2F%3E%20WHEN%20NOT%20MATCHED%20THEN%20%3CBR%20%2F%3E%20INSERT%20(%24from_id%2C%20%24to_id%2C%20PurchasedCount)%20%3CBR%20%2F%3E%20VALUES%20(Customers.%24node_id%2C%20StockItems.%24node_id%2C%20%40purchased_count)%20%3B%20%3CBR%20%2F%3E%20END%20%3CBR%20%2F%3E%20GO%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20Let%E2%80%99s%20consider%20an%20example%20to%20see%20how%20the%20MERGE%20query%20shown%20above%20works.%20Here%2C%20we%20will%20pick%20StockItemID%20226%20(White%20chocolate%20snow%20balls%20250g)%20and%20CustomerID%20946%20(David%20Safranek).%20The%20following%20query%20shows%20that%20David%20has%20bought%20two%20quantities%20of%20White%20chocolate%20snow%20balls.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22sql%22%5D%20%3CBR%20%2F%3E%20SELECT%20CustomerName%2C%20StockItemName%2C%20PurchasedCount%20%3CBR%20%2F%3E%20FROM%20Nodes.Customers%2C%20Nodes.StockItems%2C%20Edges.bought%20%3CBR%20%2F%3E%20WHERE%20MATCH%20(Customers-(bought)-%26gt%3BStockItems)%20%3CBR%20%2F%3E%20AND%20StockItemID%20%3D%20226%20%3CBR%20%2F%3E%20AND%20CustomerID%20%3D%20946%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CTABLE%3E%0A%20%20%20%3CTBODY%3E%3CTR%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20CustomerName%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20StockItemName%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20PurchasedCount%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%3C%2FTR%3E%0A%20%20%20%3CTR%3E%0A%20%20%20%20%3CTD%3EDavid%20safranek%3C%2FTD%3E%0A%20%20%20%20%3CTD%3EWhite%20chocolate%20snow%20balls%20250g%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E2%3C%2FTD%3E%0A%20%20%20%3C%2FTR%3E%0A%20%20%3C%2FTBODY%3E%3C%2FTABLE%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20Now%2C%20assume%20that%20David%20again%20bought%202%20quantities%20of%20White%20chocolate%20snow%20balls%2C%20%3CEM%3E%20WideWorldImporters%20%3C%2FEM%3E%20will%20execute%20the%20%3CEM%3E%20dbo.mergeBoughtEdge%20%3C%2FEM%3E%20stored%20procedure%20to%20run%20the%20MERGE%20statement%20on%20edge%20table%20for%20this%20transaction%20as%20follows%3A%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22sql%22%5D%20%3CBR%20%2F%3E%20exec%20dbo.mergeBoughtEdge%20946%2C%20226%2C%202%20%3CBR%20%2F%3E%20GO%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20After%20the%20merge%20statement%20completes%2C%20if%20we%20run%20the%20SELECT%20statement%20shown%20above%20again%2C%20we%20get%20following%20result.%20Note%20that%20PurchasedCount%20for%20White%20chocolate%20snow%20balls%20has%20now%20been%20updated%20to%204.%20Since%2C%20the%20edge%20already%20existed%2C%20WHEN%20MATCHED%20section%20was%20evaluated%20to%20true%20and%20update%20statement%20was%20executed%20to%20update%20the%20PurchasedCount%20value%20on%20the%20edge.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CTABLE%3E%0A%20%20%20%3CTBODY%3E%3CTR%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20CustomerName%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20StockItemName%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E%3CSTRONG%3E%20PurchasedCount%20%3C%2FSTRONG%3E%3C%2FTD%3E%0A%20%20%20%3C%2FTR%3E%0A%20%20%20%3CTR%3E%0A%20%20%20%20%3CTD%3EDavid%20safranek%3C%2FTD%3E%0A%20%20%20%20%3CTD%3EWhite%20chocolate%20snow%20balls%20250g%3C%2FTD%3E%0A%20%20%20%20%3CTD%3E4%3C%2FTD%3E%0A%20%20%20%3C%2FTR%3E%0A%20%20%3C%2FTBODY%3E%3C%2FTABLE%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId-922291677%22%20id%3D%22toc-hId-954583067%22%3EMerge%20with%20additional%20search%20condition%20on%20WHEN%20MATCHED%3C%2FH2%3E%3CBR%20%2F%3E%20Here%20is%20an%20example%20of%20MERGE%20with%20an%20extra%20search%20condition%20in%20the%20WHEN%20MATCHED%20clause.%20The%20WHEN%20MATCHED%20clause%20is%20executed%20only%20if%20the%20pattern%20in%20MATCH%20is%20true%20and%20T.Purchased_Count%20is%20not%20null.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22sql%22%5D%20%3CBR%20%2F%3E%20CREATE%20OR%20ALTER%20PROCEDURE%20dbo.mergeBoughtEdgeWithCondition%20%3CBR%20%2F%3E%20%40CustomerID%20Integer%2C%20%3CBR%20%2F%3E%20%40ProductID%20integer%2C%20%3CBR%20%2F%3E%20%40purchased_count%20integer%20%3CBR%20%2F%3E%20AS%20%3CBR%20%2F%3E%20BEGIN%20%3CBR%20%2F%3E%20MERGE%20Edges.bought%20%3CBR%20%2F%3E%20USING%20((SELECT%20%40CustomerID%2C%20%40ProductID%2C%20%40purchased_count)%20AS%20T%20(CustomerID%2C%20ProductID%2C%20Purchased_Count)%20%3CBR%20%2F%3E%20JOIN%20Nodes.Customers%20ON%20T.CustomerID%20%3D%20Customers.CustomerID%20%3CBR%20%2F%3E%20JOIN%20Nodes.StockItems%20ON%20T.ProductID%20%3D%20StockItems.StockItemID)%20%3CBR%20%2F%3E%20ON%20MATCH%20(Customers-(bought)-%26gt%3BStockItems)%20%3CBR%20%2F%3E%20WHEN%20MATCHED%20AND%20T.Purchased_Count%20%26gt%3B%200%20THEN%20%3CBR%20%2F%3E%20UPDATE%20SET%20PurchasedCount%20%3D%20PurchasedCount%20%2B%20T.Purchased_Count%20%3CBR%20%2F%3E%20WHEN%20NOT%20MATCHED%20THEN%20%3CBR%20%2F%3E%20INSERT%20(%24from_id%2C%20%24to_id%2C%20PurchasedCount)%20%3CBR%20%2F%3E%20VALUES%20(Customers.%24node_id%2C%20StockItems.%24node_id%2C%20T.Purchased_Count)%20%3B%20%3CBR%20%2F%3E%20END%20%3CBR%20%2F%3E%20GO%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20To%20run%20the%20examples%20shown%20here%2C%20download%20and%20restore%20the%20WideWorldImporters%20database%20backup%20(follow%20these%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FMicrosoft%2Fsql-server-samples%2Ftree%2Fmaster%2Fsamples%2Fdemos%2Fsql-graph%2Frecommendation-system%23before-you-begin%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20setup%20instructions%20%3C%2FA%3E%20)%20and%20then%20run%20the%20following%20scripts%20to%20create%20and%20populate%20the%20node%20and%20edge%20tables%3A%20%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FMicrosoft%2Fsql-server-samples%2Fblob%2Fmaster%2Fsamples%2Fdemos%2Fsql-graph%2Frecommendation-system%2Fbefore-you-begin.sql%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Create%20Node%20and%20Edge%20schema%20%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FMicrosoft%2Fsql-server-samples%2Fblob%2Fmaster%2Fsamples%2Fdemos%2Fsql-graph%2Frecommendation-system%2Fdemo3-create-and-populate-nodes-and-edges.sql%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20Create%20Node%20and%20Edge%20tables%20%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FOL%3E%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId--1629865284%22%20id%3D%22toc-hId--1597573894%22%3EConclusion%3C%2FH2%3E%3CBR%20%2F%3E%20UPSERT%20scenarios%20on%20graph%20tables%20can%20now%20be%20performed%20through%20a%20single%20MERGE%20statement.%20In%20this%20blog%20we%20discussed%20some%20of%20the%20scenarios%20where%20MERGE%20can%20be%20used.%20It%20can%20especially%20be%20useful%20when%20you%20would%20like%20to%20insert%2Fupdate%20edge%20data%20depending%20on%20whether%20or%20not%20an%20edge%20already%20exists%20between%20two%20nodes.%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20If%20you%20have%20feedback%20on%20this%20feature%2C%20please%20email%20us%20at%20sqlgraph%40service.microsoft.com.%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-386226%22%20slang%3D%22en-US%22%3EFirst%20published%20on%20MSDN%20on%20Jul%2016%2C%202018%20SQL%20Server%202017%20and%20Azure%20SQL%20Database%20introduced%20native%20graph%20database%20capabilities%20used%20to%20model%20many-to-many%20relationships.%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-386226%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3ESQLServerStorageEngine%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft
First published on MSDN on Jul 16, 2018
SQL Server 2017 and Azure SQL Database introduced native graph database capabilities used to model many-to-many relationships. The first implementation of SQL Graph introduced support for edges to represent relationships, nodes to represent entities and a new MATCH predicate to support graph pattern matching and traversal.

We will be further expanding the graph database capabilities with several new features. In this blog we will discuss one of these features that is now available for public preview in Azure SQL Database, MATCH support in MERGE DML for graph tables .

The MERGE statement performs insert, update, or delete operations on a target table based on the results of a join with a source table. For example, you can synchronize two tables by inserting, updating, or deleting rows in a target table based on differences between the target table and the source table. Using MATCH predicates in a MERGE statement is now supported on Azure SQL Database. That is, it is now possible to merge your current graph data (node or edge tables) with new data using the MATCH predicates to specify graph relationships in a single statement, instead of separate INSERT/UPDATE/DELETE statements.

In this post we will discuss few examples of how MATCH can be used in MERGE statement. For these examples, we have created Customers and StockItems node tables and bought edge table in the WideWorldImporters database.




Graph schema for MERGE examples: Customers bought StockItems



Merging node table data


A MERGE statement can be used to insert a new node record or update attributes on an existing record using a single statement (UPSERT). A MATCH predicate is not necessarily required for this scenario and hence, using merge to upsert node data was supported in previous releases. Here is an example: WideWorldImporters would like to create a new Customers node record when a customer buys a stockitem. If the customer already exists and a new WebsiteURL was provided, they would like to update the customer record with the new information. They can use the following MERGE DML on the Customers node table:



[code language="sql"]
CREATE OR ALTER PROCEDURE dbo.mergeCustomerNode
@CustomerID BIGINT,
@CustomerName VARCHAR(100),
@CustomerWebsiteURL VARCHAR(1000)
AS
BEGIN
MERGE Nodes.Customers AS C
USING (SELECT @CustomerID, @CustomerName, @CustomerWebsiteURL)
AS T (CustomerID, CustomerName, CustomerWebsiteURL)
ON (C.CustomerID = T.CustomerID)
WHEN MATCHED THEN
UPDATE SET WebsiteURL = T.CustomerWebsiteURL
WHEN NOT MATCHED THEN
INSERT (CustomerID, CustomerName, WebsiteURL)
VALUES (T.CustomerID, T.CustomerName, T.CustomerWebsiteURL) ;
END
GO
[/code]


Merging edge table data


With this release, users can insert a new edge record or update or delete an existing one in a single statement using the MERGE DML. For example, continuing with the graph shown above, the following MERGE DML can be used to either insert a new bought edge when a Customer buys a StockItem , or if the edge already exists then update the value of PurchasedCount attribute on the existing edge record:

[code language="sql"]
CREATE PROCEDURE dbo.mergeBoughtEdge
@CustomerID integer,
@ProductID integer,
@purchased_count integer
AS
BEGIN
MERGE Edges.bought
USING ((SELECT @CustomerID, @ProductID) AS T (CustomerID, ProductID)
JOIN Nodes.Customers ON T.CustomerID = Customers.CustomerID
JOIN Nodes.StockItems ON T.ProductID = StockItems.StockItemID)
ON MATCH (Customers-(bought)->StockItems)
WHEN MATCHED THEN
UPDATE SET PurchasedCount = PurchasedCount + @purchased_count
WHEN NOT MATCHED THEN
INSERT ($from_id, $to_id, PurchasedCount)
VALUES (Customers.$node_id, StockItems.$node_id, @purchased_count) ;
END
GO
[/code]



Let’s consider an example to see how the MERGE query shown above works. Here, we will pick StockItemID 226 (White chocolate snow balls 250g) and CustomerID 946 (David Safranek). The following query shows that David has bought two quantities of White chocolate snow balls.

[code language="sql"]
SELECT CustomerName, StockItemName, PurchasedCount
FROM Nodes.Customers, Nodes.StockItems, Edges.bought
WHERE MATCH (Customers-(bought)->StockItems)
AND StockItemID = 226
AND CustomerID = 946
[/code]


CustomerName StockItemName PurchasedCount
David safranek White chocolate snow balls 250g 2



Now, assume that David again bought 2 quantities of White chocolate snow balls, WideWorldImporters will execute the dbo.mergeBoughtEdge stored procedure to run the MERGE statement on edge table for this transaction as follows:

[code language="sql"]
exec dbo.mergeBoughtEdge 946, 226, 2
GO
[/code]

After the merge statement completes, if we run the SELECT statement shown above again, we get following result. Note that PurchasedCount for White chocolate snow balls has now been updated to 4. Since, the edge already existed, WHEN MATCHED section was evaluated to true and update statement was executed to update the PurchasedCount value on the edge.


CustomerName StockItemName PurchasedCount
David safranek White chocolate snow balls 250g 4


Merge with additional search condition on WHEN MATCHED


Here is an example of MERGE with an extra search condition in the WHEN MATCHED clause. The WHEN MATCHED clause is executed only if the pattern in MATCH is true and T.Purchased_Count is not null.

[code language="sql"]
CREATE OR ALTER PROCEDURE dbo.mergeBoughtEdgeWithCondition
@CustomerID Integer,
@ProductID integer,
@purchased_count integer
AS
BEGIN
MERGE Edges.bought
USING ((SELECT @CustomerID, @ProductID, @purchased_count) AS T (CustomerID, ProductID, Purchased_Count)
JOIN Nodes.Customers ON T.CustomerID = Customers.CustomerID
JOIN Nodes.StockItems ON T.ProductID = StockItems.StockItemID)
ON MATCH (Customers-(bought)->StockItems)
WHEN MATCHED AND T.Purchased_Count > 0 THEN
UPDATE SET PurchasedCount = PurchasedCount + T.Purchased_Count
WHEN NOT MATCHED THEN
INSERT ($from_id, $to_id, PurchasedCount)
VALUES (Customers.$node_id, StockItems.$node_id, T.Purchased_Count) ;
END
GO
[/code]



To run the examples shown here, download and restore the WideWorldImporters database backup (follow these setup instructions ) and then run the following scripts to create and populate the node and edge tables:

  1. Create Node and Edge schema

  2. Create Node and Edge tables


Conclusion


UPSERT scenarios on graph tables can now be performed through a single MERGE statement. In this blog we discussed some of the scenarios where MERGE can be used. It can especially be useful when you would like to insert/update edge data depending on whether or not an edge already exists between two nodes.

If you have feedback on this feature, please email us at sqlgraph@service.microsoft.com.