SQL insert some data - sql-insert

I need to insert data values into only some of my tables and can't find what the proper syntax should be. Here's the table for reference:
create table PERFORMER (
STAGE_NM char(15) primary key,
P_NAME varchar(10),
CHRIST_NM varchar(10)
);
Lets say I only want to insert data into STAGE_NM and P_NAME, would I go about it like this:
insert data PERFORMER values ('The Cage', 'Nicolas Cage')
Or would I have empty '' for the CHRIST_NM that I want to leave empty? Like this:
insert data PERFORMER values ('The Cage', 'Nicolas Cage', '')
I feel like it would be the first one, but I can't find anything saying that I'm right or wrong in this assumption.

Why not just be explicit in your insert statement?
insert performer (STAGE_NM, P_NAME) values ('The Cage', 'Nicolas Cage');

It's highly recommended to use a list of columns, just in case you reorder the columns later, especially since they're all strings.
insert into table (stage_nm, p_name)
values('The Cage', 'Nicolas Cage');
If you really don't want to list them and just have the values, I would recommend using NULL instead of a zero-length string, as in your example.

As mentioned here http://www.w3schools.com/sql/sql_insert_into_select.asp
You can add some column names if you don't want to insert data in all columns
INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;
So you can use
INSERT INTO Performer (STAGE_NM, P_NAME) VALUES ('The Cage', 'Nicolas Cage');
Hope it was helpful !
Bertrand

Related

Copy rows from table to another

I want to copy the rows of a table OLD into another table NEW.
INSERT INTO NEW
SELECT date, kind, id, product, version, quantity FROM OLD;
The table OLD has a column kind which is VARCHAR and contains words like insert, extract, delete. In the NEW table this column is an INTEGER. Is there a way to say that if you find delete insert 1, if you find extract insert 2 etc.. ?
This should work for you,
INSERT INTO Destination SELECT * FROM Source;
See SQL As Understood By SQLite: INSERT for a formal definition.
You can use a CASE statement to replace the string labels with integers:
INSERT INTO NEW
SELECT date,
CASE WHEN kind = 'delete' THEN 1
WHEN kind = 'extract' THEN 2
ELSE ...
END,
product,
version,
quantity
FROM OLD;
This assumes that the columns line up correctly, and all the other column types match.

SQLITE - INSERT or UPDATE without changing ROWID value

I need to update a table row IF EXISTS, otherwise INSERT a new row.
I tried:
INSERT OR REPLACE INTO table VALUES ...
but if the row row exist this statement changes the row's ROWID, and that's what I'm trying to avoid (I need the rowid :D)
I also tried to find a way to get some sort of return value from the update, in the case where an update has taken place, but I still don't understand how... If I could get the return value from the update statement, I could choose wether to proceed with an insert or not.
Do you have any suggestion or solution to this problem? Or do I need to make a copy of the ROWID and use that instead of the "pure" table ROWID?
Thanks in advance, best regards
ps: I was looking HERE and I was wondering if sqlite has the OUTPUT special word too, but google didn't help me..
---- EDIT after reading comments:
table schema example
CREATE TABLE test (
table_id TEXT NOT NULL,
some_field TEXT NOT NULL,
PRIMARY KEY(table_id)
)
INSERT or REPLACE INTO test (table_id, some_field) VALUES ("foo","bar")
I tested Chris suggestion but the rowid still gets changed. I think the best alternative is to do a SELECT to see if a row with that key already exist. If so, UPDATE, otherwise, INSERT... good old fashion but guaranteed to work.
Combine it with select, like this
INSERT or REPLACE INTO test (ROWID, table_id, some_field)
VALUES ((SELECT ROWID from test WHERE table_id = 'foo' UNION SELECT max(ROWID) + 1 from test limit 1), 'foo','bar')
You need to specify that your table_id is unique in addition to being the primary key:
sqlite> CREATE TABLE test (
table_id TEXT NOT NULL,
some_field TEXT NOT NULL,
PRIMARY KEY(table_id),
UNIQUE(table_id)
);
sqlite> insert or replace into test values("xyz", "other");
sqlite> select * FROM test;
xyz|other
sqlite> insert or replace into test values("abc", "something");
sqlite> insert or replace into test values("xyz", "whatever");
sqlite> select * FROM test;
abc|something
xyz|whatever
From version 3.24.0 (2018-06-04), SQLite now supports an UPSERT clause that will do exactly what the OP needed: https://www.sqlite.org/lang_UPSERT.html
The insert would now look like this:
INSERT INTO test (table_id, some_field) VALUES ("foo","baz")
ON CONFLICT(table_id) DO UPDATE SET some_field=excluded.some_field;

Passing parameter to IN SQL statement

I collected some values to be looked up from a DB column inside a string variable and was trying to pass this as a parameter in the SQL StoredProcedure.
ALTER PROCEDURE [dbo].[InkDB]
(
#ser nvarchar(255),
#svt nvarchar(255)
)
AS
SELECT DISTINCT Details from tbData WHERE (Name IN #svt AND Address=#ser)
This gives me a syntax error near #svt message while trying to run the query.
From my webpage, the parameter has value something like ('PersonA', 'Person B', 'Person C') that is being passed. How do I use the IN statement in this case?
I would do it with XML. Could not find this solution in the duplicate question so I add it here.
Your SP could look like this:
alter procedure InkDB
#ser nvarchar(255),
#svt xml
as
declare #T table
(
Name nvarchar(50)
)
insert into #T
select T.N.value('.', 'nvarchar(50)')
from #svt.nodes('/N') as T(N)
select distinct Details
from tbData
where Name in (select Name from #T) and
Address=#ser
And you would call it like this.
exec InkDB '', '<N>PersonA</N><N>PersonB</N>'
Dynamic Query
Alter procedure test
(
#ser nvarchar(255),
#svt nvarchar(255)
)
AS
BEGIN
declare #sql nvarchar(Max)
Set #sql='SELECT DISTINCT semester_code from mst_paper WHERE course_code IN ('+#svt+') AND branch_code='+#ser+''
exec sp_executesql #sql
END
Its a common mistake - you are passing a single value (expression) of type string to IN operator but IN expects a comma delimited list of values (expressions) and not a single string variable.
What you need to do here is to have a function that would split the given parameter into a multiple values based on given delimiter and then use that list with IN keyword. For example,
SELECT DISTINCT Details from tbData WHERE Name IN (SELECT Val FROM dbo.efn_Split(#svt, ',')) AND Address=#ser
where efn_Split is a table value function that will split comma-separated values into a table. See these various SO questions for implementation of such function:
Split function equivalent in T-SQL?
How to split string using delimiter char using T-SQL?
Yet another alternative is to construct the SQL statement and execute with sp_executesql.
IN needs to be as follows:
... IN (#param1, #param2, ...)
So, you should do:
SELECT DISTINCT Details from tbData WHERE Name IN (#svt) AND Address=#ser
Update:
The alter procedure statement you provided in your question is syntactically incorrect. My answer provides the correct syntax for writing the statement and it compiles.
Reading your question over again, I see you have in fact have two issues. The first was a syntax error and the second passing in a comma delimited list in a single parameter.
The answer is you simply cannot provided a comma delimited list of values at runtime into a single string type parameter that is used in the IN (...) clause. Now, on this second point, I would argue that this is not a good design/programming approach to the problem, but it can be done using dynamic SQL or parsing out each value from the string parameter, store them into a temp table then revise your query to join to that, or use a (or use a table valued function and store the parsed items there, where it can be queried from.
Below is the corrected syntax for your code, but it would not solve the second aspect of passing in a string containing a comma delimited list of values. That could be solved as I described above.
For the syntax error, first, you can create a dummy table to test your code. Note, a typical database table should have a primary key. This is strictly a dummy table to test the statement:
CREATE TABLE TbData(
Name nvarchar(255),
Details nvarchar(255),
Address nvarchar(255)
);
Then, you can create the initial stored procedure:
CREATE PROCEDURE Test
(
#ser nvarchar(255),
#svt nvarchar(255)
)
AS
BEGIN
SELECT DISTINCT Details FROM tbData WHERE Name IN (#ser) AND Address = #svt
END
And finally, execute the alter stored procedure statement you had asked about:
ALTER PROCEDURE Test
(
#ser nvarchar(255),
#svt nvarchar(255)
)
AS
BEGIN
SELECT DISTINCT Details FROM tbData WHERE Name IN (#ser) AND Address = #svt
END

SQLite full text search indexes

I currently have a diagnosis table. I want to make the code and description fields searchable using FTS. As I understand it though, FTS tables don't support indexes and I need to be able to lookup Diagnosis by diagnosisID very quickly. Am I going to have to create a second virtual table with all of the data duplicated just for full text searching or am I missing a solution where I dont have to duplicate all of my diagnosis codes and descriptions?
CREATE TABLE Diagnosis (
diagnosisID INTEGER PRIMARY KEY NOT NULL,
code TEXT,
collect INTEGER NOT NULL,
description TEXT
);
Turns out an FTS table has a hidden rowid field, which you can populate when you are entering data:
sqlite> create virtual table test1 using fts3;
sqlite> insert into test1 values ("This is a document!");
sqlite> insert into test1(docid,content) values (5,"this is another document");
sqlite> select rowid,* from test1;
1|This is a document!
5|this is another document
You could create an integer field in your standard table that refers to the FTS table by rowid, and move the columns you wish to make text-searchable into the FTS table.
All the info you need here :)

Keep first and remove dupliciate rows only using sqlite

Maybe i should do this in C# but i have more then one row with linkId X. I would like to remove it but i am unsure how. In code i could just use a foreach from 0 to n and remove any found rows with a greater (or !=) id but thats in code. Is there a less difficult way of doing it using sqlite?
Assuming the table's name is tableName and there is a primary key field named id, the following sql would do it. I think the following SQL query is general enough and should be able to be executed under any database engine.
delete from tableName
where id not in (
select min(id) from tableName
group by linkId
)

Resources