Cannot convert utf-8 in Stored Procedure SQL - sql

I'm stuck in the utf-8 format. I used CAST or CONVERT USING UTF-8. Even I set character N in front of query string but it's still not working.
My stored procedure:
ALTER PROCEDURE [dbo].[SPC_SP_HSDXTChinh_BangSo4_Fake]
#idDuAn NUMERIC(18, 0),
#idGoiThau NUMERIC(18, 0),
#idDonVi INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #resultString NVARCHAR(MAX);
DECLARE #queryString NVARCHAR(MAX);
DECLARE #Str_TinhHopLe NVARCHAR(255), #Str_DanhGia NVARCHAR(255), #Str_XepHang NVARCHAR(255);
SET #Str_TinhHopLe = 'N''Kết quả đánh giá tính hợp lệ của HSĐXTC''';
SET #Str_DanhGia = 'N''Giá đánh giá''';
SET #Str_XepHang = 'N''Xếp hạng các HSDT''';
SELECT #resultString = COALESCE(#resultString + ',', '') + RES.TenNhaThau
FROM (
SELECT '[' + TenNhaThau + ']' AS TenNhaThau
FROM [SPC_fn_HSDXTChinh_NhaThau_CoTinhHopLe] (#idDuAn, #idGoiThau, #idDonVi)
) RES
--PRINT #resultString
PRINT #Str_TinhHopLe;
SET #queryString = '
SELECT *
FROM (
SELECT 1 AS STT,' + #Str_TinhHopLe + ' AS NoiDung,
CAST(RES.TenNhaThau AS NVARCHAR(255)) AS TenNhaThau,
CAST(RES.KetQuaDanhGia AS VARCHAR(25)) AS KetQuaDanhGia
FROM [SPC_fn_HSDXKThuat_BangSo4] (' + CAST(#idDuAn AS VARCHAR(20)) + ',' + CAST(#idGoiThau AS VARCHAR(20)) + ',' + CAST(#idDonVi AS VARCHAR(10)) + ') RES
) SRC
PIVOT(MAX(KetQuaDanhGia) FOR TenNhaThau IN (' + #resultString + ')) P
UNION ALL
SELECT *
FROM (
SELECT 2 AS STT
,' + #Str_DanhGia + ' AS NoiDung,
CAST(RES.TenNhaThau AS NVARCHAR(255)) AS TenNhaThau,
CAST(RES.GiaTri AS VARCHAR(25)) AS GiaTri
FROM [SPC_fn_HSDXKThuat_BangSo4] (' + CAST(#idDuAn AS VARCHAR(20)) + ',' + CAST(#idGoiThau AS VARCHAR(20)) + ',' + CAST(#idDonVi AS VARCHAR(10)) + ') RES
) SRC2
PIVOT(MAX(GiaTri) FOR TenNhaThau IN (' + #resultString + ')) P
UNION ALL
SELECT *
FROM (
SELECT 3 AS STT
,' + #Str_XepHang + ' AS NoiDung,
CAST(RES.TenNhaThau AS NVARCHAR(255)) AS TenNhaThau,
CAST(ROW_NUMBER() OVER(ORDER BY GiaTri) AS VARCHAR(25)) AS XepHang
FROM [SPC_fn_HSDXKThuat_BangSo4] (' + CAST(#idDuAn AS VARCHAR(20)) + ',' + CAST(#idGoiThau AS VARCHAR(20)) + ',' + CAST(#idDonVi AS VARCHAR(10)) + ') RES
) SRC2
PIVOT(MAX(XepHang) FOR TenNhaThau IN (' + #resultString + ')) P
';
PRINT #queryString;
EXEC (#queryString);
END
A part of output messages after run stored:
SELECT
1 AS STT,
N'K?t qu? dánh giá tính h?p l? c?a HSÐXTC' AS NoiDung,
CAST(RES.TenNhaThau AS NVARCHAR(255)) AS TenNhaThau,
CAST(RES.KetQuaDanhGia AS VARCHAR(25)) AS KetQuaDanhGia
FROM
[SPC_fn_HSDXKThuat_BangSo4] (60006000000000166, 60006000000000347, 60006) RES
You can see error text: N'K?t qu? dánh giá tính h?p l? c?a HSÐXTC'.
I want to output: Kết quả đánh giá tính hợp lệ của HSĐXTC
How can I fix this?

Change these lines in your procedure:
SET #Str_TinhHopLe = N'Kết quả đánh giá tính hợp lệ của HSĐXTC';
SET #Str_DanhGia = N'Giá đánh giá';
SET #Str_XepHang = N''Xếp hạng các HSDT';

Related

Conversion failing when applying PIVOTED SCRIPT

i am having a data conversion issues when applying this un-pivoted script on my dynamic columns SSRS report .every time SSRS Report is executed the header columns are supposedly to change .
IF OBJECT_ID('tempdb..##Temp') IS NOT NULL
DROP TABLE ##Temp;
DECLARE #ObjectName VARCHAR(100) = '[AdventureWorks2016].[Sales].[SalesOrderHeader]' ,
#KeyColumn VARCHAR(100) = '[SalesOrderID]';
DECLARE #ColumnNames NVARCHAR(MAX)= '' ,
#Values NVARCHAR(MAX)= '' ,
#SQL NVARCHAR(MAX)= '';
SELECT #ColumnNames += ',
' + QUOTENAME([ShipDate]) ,
#Values += ',
' + QUOTENAME([ShipDate]) + ' = CONVERT(VARCHAR(100), '
+ QUOTENAME([ShipDate]) + ')'
FROM [AdventureWorks2016].[Sales].[SalesOrderHeader]
WHERE '[Sales].[SalesOrderHeader]' = #ObjectName
AND [ShipDate] <> #KeyColumn;
SET #SQL = N'Select * into ##Temp
FROM
(
SELECT ' + #KeyColumn + #Values + '
FROM ' + #ObjectName + '
) AS DRV
UNPIVOT
(
Value FOR ColumnName IN (' + STUFF(#ColumnNames, 1, 1, '') + ')
) AS UnPVT;';
EXEC sp_executesql #SQL;
SELECT *
FROM ##Temp

Can this dynamic SQL be replaced with the regular SQL to improve performance?

I am using the following dynamic query, but see that the performance is slow. I am not a big fan of dynamic SQL, and am looking for, if possible, a good clean and fast SQL alternative for the following. Thanks a million ton in advance! Here are some details:
In the following code, the final table missingfields_xxxx lists out the rows where we have a missing rule field.
table_name has the column rule that holds the column name of the table trans_modelname (this table can be found in the dynamic part of the sql)
DECLARE #rule NVARCHAR(MAX)
DECLARE #PeriodNumber INT = 1
DECLARE #SelectList NVARCHAR(MAX)
DECLARE #WhereList NVARCHAR(MAX)
DECLARE #SQL NVARCHAR(MAX)
DECLARE #ModelName as NVARCHAR(MAX) = 'modelname'
--DECLARE #MaxPeriods INT = 8
DECLARE #MaxPeriods INT
SELECT #MaxPeriods = count (*)
FROM
(
SELECT [rule]
FROM table_name
WHERE ModelName = #ModelName) ab
DECLARE db_cursor3 CURSOR FOR
SELECT * FROM
(
SELECT [rule]
FROM table_name
WHERE ModelName = #ModelName) cd
OPEN db_cursor3
FETCH NEXT FROM db_cursor3 INTO #rule
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN
SELECT #SelectList = COALESCE(#SelectList + ', ', '') + '' + #rule + ' AS [GLSegment_' + RIGHT('00' + CAST(#PeriodNumber AS VARCHAR), 3) + ']'
SELECT #SelectList as 'Selectlist'
IF #PeriodNumber < #MaxPeriods
BEGIN
SELECT #WhereList = COALESCE(#WhereList, '') + '(isnull([GLSegment_' + RIGHT('00' + CAST(#PeriodNumber AS VARCHAR), 3) + '],'''') = '''' ) OR '
SELECT #WhereList as 'Wherelist where periodnumber < maxperiods'
END
ELSE IF #PeriodNumber = #MaxPeriods
BEGIN
SELECT #WhereList = COALESCE(#WhereList, '') + '(isnull([GLSegment_' + RIGHT('00' + CAST(#PeriodNumber AS VARCHAR), 3) + '], '''') = '''' )'
SELECT #WhereList as 'Wherelist where periodnumber = maxperiods'
END
SET #PeriodNumber = #PeriodNumber + 1
END
FETCH NEXT FROM db_cursor3 INTO #rule
END
CLOSE db_cursor3
DEALLOCATE db_cursor3
-- build dynamic query
SET #SQL =
'SELECT * into missingfields_' + #ModelName + ' from trans_' + #ModelName + '
WHERE id in
(
SELECT id from
(
SELECT id, ' + #SelectList + '
FROM trans_' + #ModelName + ')A
WHERE ' + #WhereList + '
);
SELECT * from missingfields_' + #ModelName
PRINT #SQL
print 'missingfields_' + #ModelName
EXEC sp_executesql #SQL

Dynamic SQL - parametrized query

I use dynamic sql with parameters and have problem :)
In block of code it works, but when I call procedure I have error that I need to declare scalar variable #name_dummy
So:
DECLARE #START_TIME DATETIME = GETDATE()
DECLARE #TMP_NAMES TABLE (
SCHEMA_N VARCHAR(500),
TABLE_N VARCHAR(500),
CONDITION VARCHAR(MAX),
TARGETDB VARCHAR(500),
SOURCEDB VARCHAR(500),
COLUMN_LIST VARCHAR(MAX)
)
DECLARE #SCHEMA_N VARCHAR(500)
DECLARE #TABLE_N VARCHAR(500)
DECLARE #CONDITION VARCHAR(MAX)
DECLARE #COLUMN_LIST VARCHAR(MAX)
DECLARE #TARGETDB VARCHAR(500)
DECLARE #SOURCEDB VARCHAR(500)
INSERT INTO #TMP_NAMES
SELECT
o.SCHEMA_N
,o.TABLE_N
,o.Condition
,o.TargetDB
,o.SourceDB
,STUFF((SELECT
', ' + c.name
FROM sys.columns c
WHERE c.object_id = o.object_id
AND c.system_type_id <> 189 /* Pomijam timestamp*/
ORDER BY c.column_id
FOR XML PATH (''))
, 1, 1, '')
FROM Table_A o
ORDER BY 1,
2
SELECT
SCHEMA_N
,TABLE_N
,CONDITION
,TARGETDB
,SOURCEDB
,COLUMN_LIST
FROM #TMP_NAMES
DECLARE KUR CURSOR
FOR
SELECT
SCHEMA_N
,TABLE_N
,CONDITION
,TARGETDB
,SOURCEDB
,COLUMN_LIST
FROM #TMP_NAMES
OPEN KUR
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #TOP VARCHAR(100)
SET #TOP = ( SELECT CAST(Wartosc AS VARCHAR) FROM Table_B WHERE Id = 3 )
IF #TOP < 40000
SET #TOP = 40000
WHILE ( 1 = 1 )
BEGIN
DECLARE #CHECK BIT = 0
DECLARE #sqlCMD NVARCHAR(MAX) = 'SELECT TOP 1 #check_exists = 1 FROM '
+ #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #START_TIME;
SELECT #sqlCMD , #CHECK
END
END
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
CLOSE KUR;
DEALLOCATE KUR
And when I execute this it's compiling and works ( returns values ) for example sql which I want to execute.
SELECT TOP 1 #check_exists = 1 FROM MSSF15_WarstwaPosrednia.KatalogZdarzen.MSSF_RaportZdarzenPLKB2CS2K WHERE StatusPrzetwarzania = 4 AND DataWpisu < DATEADD(MONTH, -3, #START_TIME)
Parameters work here ( #check_exists which is output and #START_TIME condition param ) , but when I execute this in procedure I'm getting error
Must declare the scalar variable "#START_TIME". 137
SP definition:
USE xxxx
/****** Object: StoredProcedure dbo.dummy Script Date: 06/09/2018 13:40:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE dbo.dummy
AS
BEGIN
/*
PRZENIESIENIE DANYCH
*/
DECLARE #START_TIME DATETIME = GETDATE()
DECLARE #TMP_NAMES TABLE (
SCHEMA_N VARCHAR(500),
TABLE_N VARCHAR(500),
CONDITION VARCHAR(MAX),
TARGETDB VARCHAR(500),
SOURCEDB VARCHAR(500),
COLUMN_LIST VARCHAR(MAX)
)
DECLARE #SCHEMA_N VARCHAR(500)
DECLARE #TABLE_N VARCHAR(500)
DECLARE #CONDITION VARCHAR(MAX)
DECLARE #COLUMN_LIST VARCHAR(MAX)
DECLARE #TARGETDB VARCHAR(500)
DECLARE #SOURCEDB VARCHAR(500)
INSERT INTO #TMP_NAMES
SELECT o.SCHEMA_N,
o.TABLE_N,
o.Condition,
o.TargetDB,
o.SourceDB,
STUFF((
SELECT ', ' + c.NAME
FROM sys.columns c
WHERE c.object_id = o.object_id
AND c.system_type_id <> 189 /* Pomijam timestamp*/
ORDER BY c.column_id
FOR XML PATH('')
), 1, 1, '')
FROM dbo.Table_A o
ORDER BY 1,
2
SELECT SCHEMA_N,
TABLE_N,
CONDITION,
TARGETDB,
SOURCEDB,
COLUMN_LIST
FROM #TMP_NAMES
DECLARE KUR CURSOR
FOR
SELECT SCHEMA_N,
TABLE_N,
CONDITION,
TARGETDB,
SOURCEDB,
COLUMN_LIST
FROM #TMP_NAMES
OPEN KUR
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #TOP VARCHAR(100)
SET #TOP = (
SELECT CAST(Wartosc AS VARCHAR)
FROM dbo.Table_B
WHERE Id = 3
)
IF #TOP < 40000
SET #TOP = 40000
WHILE (1 = 1)
BEGIN
BEGIN TRY
BEGIN TRANSACTION T_TEST
DECLARE #CHECK BIT = 0
DECLARE #START_TIME_P DATE = GETDATE()
DECLARE #sqlCMD NVARCHAR(MAX) = 'SELECT TOP 1 #check_exists = 1 FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
SELECT #CHECK,
#START_TIME_P,
#sqlCMD
EXEC sp_executesql #sqlCMD,
N'#check_exists bit OUTPUT, #START_TIME DATE',
#check_exists = #CHECK OUTPUT,
#START_TIME = #START_TIME_P;
IF OBJECT_ID('tempdb..#TMP_ID') IS NOT NULL
DROP TABLE #TMP_ID
CREATE TABLE #TMP_ID (Id INT)
EXEC (
'INSERT INTO #TMP_ID
SELECT TOP ' + #TOP + ' Id
FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
)
DECLARE #sqlCMD_Ins NVARCHAR(MAX)
SET #sqlCMD_Ins = 'INSERT INTO ' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' '
SET #sqlCMD_Ins = #sqlCMD_Ins + 'SELECT ' + #COLUMN_LIST + ' FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE Id IN ( SELECT Id FROM #TMP_ID )'
IF #sqlCMD_Ins IS NULL
RAISERROR (
'Brak polecenia insert #sqlCMD_Ins',
16,
1
)
EXEC (#sqlCMD_Ins)
DECLARE #sqlCMD_Del NVARCHAR(MAX)
SET #sqlCMD_Del = 'DELETE FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE Id IN ( SELECT Id FROM #TMP_ID )'
IF #sqlCMD_Del IS NULL
RAISERROR (
'Brak polecenia insert #sqlCMD_Ins',
16,
1
)
EXEC (#sqlCMD_Del)
DROP TABLE #TMP_ID
COMMIT TRANSACTION T_TEST
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
BEGIN
ROLLBACK TRANSACTION T_TEST
PRINT 'Wycofanie zmian'
PRINT ERROR_MESSAGE() + ' ' + CAST(ERROR_NUMBER() AS VARCHAR(256))
END
END CATCH
IF #CHECK = 0
BREAK
END
EXEC ('SELECT ''' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ''' AS DB ,COUNT(1) AS ILOSC FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' UNION ALL ' + 'SELECT ''' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ''' AS DB ,COUNT(1) AS ILOSC FROM ' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N)
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
END
CLOSE KUR;
DEALLOCATE KUR;
DECLARE #END_TIME DATETIME = GETDATE()
SELECT 'Daty przetworzenia',
#START_TIME_P AS 'START',
#END_TIME AS 'END'
SELECT 'Czas (min)',
DATEDIFF(MINUTE, #START_TIME_P, #END_TIME)
END
Guys, maybe u have similar situation and can help.
Error msg
Wycofanie zmian
Must declare the scalar variable "#START_TIME". 137
Thanks
Instead of
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #START_TIME;
try
declare #date_in DATE = GETDATE()
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #date_in;

Population of Visual Studio Database Project data-loading scripts from existing data

So, I've been hunting for a solution for this for awhile and have come up with what sort of works ... but I can't help feeling that there must be something more elegant.
What I'm looking for is to be able to extract existing data from a populated database & incorporate that data into loading scripts. The database schema & configuration data will be rolled out multiple times, and will change as development continues, so it's important to be able to rebuild the configuration data from existing data, rather than from static data kept in scripts.
Here's what I've cobbled together:
create procedure #dump (
#TableName varchar(128)
)
as
set nocount on
set rowcount 0
declare #template varchar(max)
set #template = 'SET IDENTITY_INSERT [dbo].[' + #TableName + '] ON
MERGE INTO [dbo].[' + #TableName + '] AS [Target]
USING
(
VALUES
{vals}
)
AS [Source] ({fields})
ON [Target].[{pk}] = [Source].[{pk}]
WHEN MATCHED THEN UPDATE SET
{upds}
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
{fields}
)
VALUES
(
{fields}
);
SET IDENTITY_INSERT [dbo].[' + #TableName + '] OFF
--------------------------------------------------
'
declare #pk varchar(max) = ''
declare #vals varchar(max) = '/*
set concat_null_yields_null off
select ''' + '(' + ''' + replace(replace({casts} + '') ,'', '',,'', '', null,''), ''' + ',)' + ''', ''' + ',null)' + ''') from [' + #TableName + ']
*/'
declare #casts varchar(max) = ''
declare #fields varchar(max) = ''
declare #upds varchar(max) = ''
declare #inserts varchar(max) = ''
set #pk = SUBSTRING(#TableName, 1, len(#TableName) - 1) + 'ID'
declare cur_flds
cursor for select c.name, c.type
from syscolumns c
where c.id = object_id(#TableName)
order by c.colid
declare #fn varchar(max)
declare #ft int
open cur_flds
fetch next from cur_flds into #fn, #ft
while ##FETCH_STATUS = 0
begin
if len(#fields) > 0
set #fields = #fields + ', '
set #fields = #fields + '[' + #fn + ']'
if len(#casts) > 0
set #casts = #casts + ' + ' + ''','' + '
if #ft in(56,55,50,38,48)
set #casts = #casts + 'cast([' + #fn + '] as varchar)'
else if #ft = 111
set #casts = #casts + ''''''''' + ' + 'cast([' + #fn + '] as varchar) + ' + ''''''''''
else
set #casts = #casts + ''''''''' + ' + 'replace([' + #fn + '], ''''''''' + ', ' + ''''''''''''') + '''''''''
if #fn != #pk
begin
if len(#upds) > 0
set #upds = #upds + ', '
set #upds = #upds + '[Target].[' + #fn + '] = [Source].[' + #fn + ']'
end
fetch next from cur_flds into #fn, #ft
end
close cur_flds
deallocate cur_flds
set #vals = REPLACE(#vals, '{casts}', #casts)
set #template = REPLACE(#template, '{pk}', #pk)
set #template = REPLACE(#template, '{vals}', #vals)
set #template = REPLACE(#template, '{fields}', #fields)
set #template = REPLACE(#template, '{upds}', #upds)
set #template = REPLACE(#template, '{inserts}', #inserts)
print #template
go
exec #dump 'ActionItemSystems'
drop proc #dump
That ends up giving me output of:
SET IDENTITY_INSERT [dbo].[ActionItemSystems] ON
MERGE INTO [dbo].[ActionItemSystems] AS [Target]
USING
(
VALUES
/*
set concat_null_yields_null off
select '(' + replace(replace(cast([ActionItemSystemID] as varchar) + ',' + '''' + replace([ActionItemSystemName], '''', '''''') + '''' + ') ,', ',,', ', null,'), ',)', ',null)') from [ActionItemSystems]
*/
)
AS [Source] ([ActionItemSystemID], [ActionItemSystemName])
ON [Target].[ActionItemSystemID] = [Source].[ActionItemSystemID]
WHEN MATCHED THEN UPDATE SET
[Target].[ActionItemSystemName] = [Source].[ActionItemSystemName]
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
[ActionItemSystemID], [ActionItemSystemName]
)
VALUES
(
[ActionItemSystemID], [ActionItemSystemName]
);
SET IDENTITY_INSERT [dbo].[ActionItemSystems] OFF
From this point, I can take the commented-out bit
set concat_null_yields_null off
select '(' + replace(replace(cast([ActionItemSystemID] as varchar) + ',' + '''' + replace([ActionItemSystemName], '''', '''''') + '''' + ') ,', ',,', ', null,'), ',)', ',null)') from [ActionItemSystems]
execute that, and get output like:
(33,'7111-5 -Upstream/Seed Lab') ,
(32,'7301-Seed Lab') ,
(30,'7807 UFDF') ,
(14,'BAS Panel Upgrade') ,
(1,'Clean Steam') ,
(13,'DCS') ,
(2,'HWFI') ,
(3,'MCS') ,
(12,'MES') ,
(31,'Seed Lab') ,
(18,'UCS WRO') ,
(34,'Upstream Seed Lab') ,
(29,'Viral Filtration') ,
which can then be incorporated (sans the final comma) into the script.
Now, this solution functions, but it's fragile. It depends on various assumptions (e.g., that the Table Name will have a Primary Key of Table Name - trailing 's' and plus ID) that may not hold true for every solution. It also requires cutting & pasting, and rerunning from the start when the table structures change.
This is probably quite a lot of background ... which I'm partly sharing because I couldn't find anything similar out there & thought that somebody might benefit from this. However, I still come back to my real question, which is to say: where's the tool to generate this kind of script for VS Database Projects? There really should be something - something that would take into account whatever the primary key is, that would generate the thing entire, etc.
You can try with this procedure for generating MERGE statements:
https://github.com/readyroll/generate-sql-merge
It is more advanced version of what you already have.

SQL Server: Error message on dynamic procecure

I don't have much experience with dynamic procedures so the following was only an attempt.
The only part that is actually dynamic here is the table name which I tried to create by combining the fix part "MOC_" and the variable part #level.
Can someone tell me what I have to change here to make this work ?
The error I get when executing this points to the IF NOT EXISTS part:
Conversion failed when converting the nvarchar value 'IF NOT EXISTS (
SELECT *
FROM MOC_Nav2
WHERE itemID = ' to data type int.
My procedure:
ALTER PROCEDURE [dbo].[MOC_UpdateNav]
#level nvarchar(20),
#itemID int,
#parentID int,
#itemName nvarchar(100),
#sortID int,
#logStatus nvarchar(20),
#lastUpdate nvarchar(50),
#modBy varchar(50)
AS
BEGIN
SET NOCOUNT ON;
BEGIN
DECLARE #sql nvarchar(max)
SET #sql = 'IF NOT EXISTS
(
SELECT *
FROM MOC_' + #level + '
WHERE itemID = ' + #itemID + '
)
INSERT INTO MOC_' + #level + '
(
parentID,
itemName,
sortID,
logStatus,
lastUpdate,
modDate,
modBy
)
SELECT ' + #parentID + ',
' + #itemName + ',
' + #sortID + ',
' + #logStatus + ',
' + #lastUpdate + ',
GETDATE(),
' + #modBy + '
ELSE
UPDATE MOC_' + #level + '
SET parentID = ' + #parentID + ',
itemName = ' + #itemName + ',
sortID = ' + #sortID + ',
logStatus = ' + #logStatus + ',
lastUpdate = ' + #lastUpdate + ',
modDate = GETDATE(),
modBy = ' + #modBy + '
WHERE itemID = ' + #itemID + ''
EXEC(#sql)
END
END
#itemID is an int. Because it is used in the expression, everything else must be converted to a number, including your SQL text.
Convert #itemID (and other numbers) to nvarchar before concatenating it into the query:
SET #sql = N'IF NOT EXISTS
(
SELECT *
FROM MOC_' + #level + '
WHERE itemID = ' + cast(#itemID as nvarchar(30)) + ...