Search code examples
jsonsql-servert-sqlsql-insertinsert-update

Create table and insert rows if doesn't exist, else just insert


I am able to create table, shred JSON and add data if it does not exist in SQL Server:

DECLARE @json nvarchar(max);

SET @json = N'[{"IplayerName": "Pilipiliz",
                 "Sname": "kikombe",
                 "WeightLBs":"60.236"
               }]'

IF NOT EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = object_id('Iplayerds')) 
BEGIN
    SELECT
        [IplayerName],
        [Sname],
        [WeightLBs]
    INTO
        Iplayerds
    FROM
        OPENJSON(@json) 
        WITH (IplayerName NVARCHAR(200),
              Sname NVARCHAR(20),
              WeightLBs DECIMAL(10,4)
             )
END
ELSE
    PRINT 'exists'

However, when I try to replace the print statement with insert rows code shown below, it fails

INSERT INTO Iplayerds (IplayerName, Sname, WeightLBs)
VALUES ([IplayerName], [Sname], [WeightLBs]
FROM OPENJSON(@json))

What am I doing wrong?


Solution

  • The INSERT command comes in two flavors:

    (1) either you have all your values available, as literals or SQL Server variables - in that case, you can use the INSERT .. VALUES() approach:

    INSERT INTO dbo.Iplayerds (IplayerName, Sname, WeightLBs)
    VALUES (@IplayerName, @Sname, @WeightLBs)
    

    Note: I would recommend to always explicitly specify the list of column to insert data into - that way, you won't have any nasty surprises if suddenly your table has an extra column, or if your tables has an IDENTITY or computed column. Yes - it's a tiny bit more work - once - but then you have your INSERT statement as solid as it can be and you won't have to constantly fiddle around with it if your table changes.

    (2) if you don't have all your values as literals and/or variables, but instead you want to rely on another table, multiple tables, or views, to provide the values, then you can use the INSERT ... SELECT ... approach:

    INSERT INTO dbo.Iplayerds (IplayerName, Sname, WeightLBs)
       SELECT
           [IplayerName], [Sname], [WeightLBs]
       FROM 
           OPENJSON(@json) WITH (IplayerName NVARCHAR(200),
                                 Sname NVARCHAR(20),
                                 WeightLBs DECIMAL(10,4)
                                )           
    

    Here, you must define exactly as many items in the SELECT as your INSERT expects - and those can be columns from the table(s) (or view(s)), or those can be literals or variables. Again: explicitly provide the list of columns to insert into - see above.

    You can use one or the other - but you cannot mix the two - you cannot use VALUES(...) and then have a SELECT query in the middle of your list of values - pick one of the two - stick with it.