How to select default value that was created as create default and then was binded to user defined data type? - sql

There is a table with all fields of user defined data types and NOT NULL. There are some defaults created as CREATE DEFAULT and binded to those user defined data types. It is given that way and I may not change it.
I need to insert data into this table from the source where there are some NULLS. How to use those defaults in my insert?
I've tried to get these defaults using defenition from sys.default_constraints, but there are no defaults created as CREATE DEFAULT in sys.default_constraints.
'''SQL
--Code I may not change
CREATE TYPE dt_myType FROM varchar(255) NOT NULL
GO
CREATE DEFAULT myDefault
AS
''
GO
EXEC sp_bindefault 'myDefault', 'dt_myType';
GO
CREATE TABLE myTable (
f1 dt_myType NOT NULL )
GO
--My code
insert into myTable
(f1)
select
case f
when 1 then 'example'
else --I need default here
end
from ...
'''

If you do not have very many columns to test, you could do something like this:
insert into t (<other columns>, a, b)
select <other columns>, x.a, x.b
from x
where x.a is not null and x.b is not null;
insert into t (<other columns>, a )
select <other columns>, x.a
from x
where x.a is not null and x.b is null;
insert into t (<other columns>, b )
select <other columns>, x.b
from x
where x.a is null and x.b is not null;
insert into t (<other columns>)
select <other columns>
from x
where x.a is null and x.b is null;
This doesn't generalize well to many more columns.
Otherwise, here are some options I can think of:
Loop through each record (say using a dreaded cursor) and construct the insert based on the presence of NULL values.
Use an instead of trigger to basically construct the inserts, as described above.
Insert the data so all values are default values and then update them with the values in the data.
Figure out a way to parse the default value in the metadata, represent it as the appropriate type, and include it in your query.

Related

INSERT row in table a for every row in table b [duplicate]

If I have an SQL table with all default columns (e.g. identity column + any number of columns all with default values), what is the SQL statement to insert a row with no explicit values given?
insert MyTable /* ( doh, no fields! ) */
-- values( doh, no values! )
What's the trick?
This is a part of the INSERT syntax
INSERT INTO TableName DEFAULT VALUES
Read more here:
https://learn.microsoft.com/en-us/sql/t-sql/statements/insert-transact-sql
You can use the DEFAULT keyword.
The accepted answer only works for one row, not for multiple rows.
Let us assume you know how many rows to insert, but you want all default values. You cannot do the following, for instance
INSERT MyTable
SELECT DEFAULT VALUES -- Incorrect syntax near the keyword 'DEFAULT'.
FROM SomeQueryOrView;
-- or
INSERT MyTable
DEFAULT VALUES -- Incorrect syntax near the keyword 'FROM'.
FROM SomeQueryOrView;
Instead we can hack MERGE to do this
MERGE INTO myTable
USING (SELECT SomeValue FROM SomeQueryOrView) s
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT DEFAULT VALUES;
A bonus benefit is that we can OUTPUT data from columns which are not being inserted:
MERGE INTO myTable
USING (SELECT SomeValue FROM SomeQueryOrView) s
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT DEFAULT VALUES
OUTPUT inserted.Id, s.SomeValue;

While updating table1, how do I INSERT to table2 for every change in table 1?

I have a MEMBER table and NOTIFICATION table. On client side, I list all of the records in MEMBER table and there is a points column and this is shown as text input. So after I change the values for some members, I can click save button and this will update the records in my MEMBER table that's all right,
But the thing I want to accomplish is for every record whose points value has changed I want to INSERT a record in my notifications table.
I couldn't think of anything, how can I approach to this problem?
For notifications I made 3 tables by following the article in here
Use the output clause instead of trigger, they are bad.
You need the condition "where data_old <> data_new" case if you updated a column with the same value, SQL Server marked it as changed, even if the value hasn't changed
create table #example (id int identity(1,1) not null, data nvarchar(max));
insert into #example (data) values ('value 1'),('value 2'), ('value 3');
create table #audit (id int, data_old nvarchar(max), data_new nvarchar(max), [When] datetime not null default (getdate()));
insert into #audit (id, data_old, data_new)
select id, data_old, data_new
from (
update #example
set data = 'value changed'
output inserted.id, deleted.data as data_old, inserted.data as data_new
where id = 2
)changed (id, data_old, data_new)
where data_old <> data_new
select * from #audit
will result with this in #audit :
You have described what a trigger does.
create trigger trig_member_insert on members after update
as
begin
insert into notifications ( . . . )
select . . ., i.points as new_points u.points as old_points -- what you want to insert
from inserted i join
updated u
on i.member_id = u.member_id
where u.points <> i.points
end;
Storing something called "points" as a string seems like a very poor choice. It sounds like a number.

Does sqlite has something like case on procedural Level?

I have a simple, as it looks, question:
I am having Sqlite query where I am using temp tables and then joining those table, something like:
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
Now is it possible to create some sort of procedura if or case so for example one of those insert will not be executed, like:
bool merge = false;
drop table if exists SourceA
create temp table SourceA (id int, value text);
insert into SourceA select id, value from TableA
if(merge)
{
drop table if exists SourceB
create temp table SourceB (id int, value text);
insert into SourceB select id, value from TableB
select SourceA.*, SourceB.* from SourceA join SourceB on SourceA.id = SourceB.id
else
{
select * from SourceA
}
Example of usage is simple, its like a condition when you determine seconds two dates, let's say second table counts missing seconds, so now if interval is too big app will crush. So i need to determine outside of SQL if such thing can be done, and pass it to SQL (basically it can be any condition that will exclude second insert from happening)
I've mange to handle my problem by using variables temp table like:
drop table if exists Variables;
create temp table Variables (MinDatetime Datetime, MaxDatetime Datetime);
insert into Variables Values(#MinDatetime, #MaxDatetime);
And then passing parameter from code, an just omitting result using case something like:
case when (Select MinDatetime from Variables) = 'None' or (Select MaxDatetime from Variables) = 'None' then 0
else value
end as value
And if value is 'None' it will return just plain 0
SQLite is designed as an embedded database, to be used together with a 'real' programming language, so it does not have any procedural features.
Put the control logic into your actual program (or, if you don't have one, write a script).

How to manipulate comma-separated list in SQL Server

I have a list of values such as
1,2,3,4...
that will be passed into my SQL query.
I need to have these values stored in a table variable. So essentially I need something like this:
declare #t (num int)
insert into #t values (1),(2),(3),(4)...
Is it possible to do that formatting in SQL Server? (turning 1,2,3,4... into (1),(2),(3),(4)...
Note: I can not change what those values look like before they get to my SQL script; I'm stuck with that list. also it may not always be 4 values; it could 1 or more.
Edit to show what values look like: under normal circumstances, this is how it would work:
select t.pk
from a_table t
where t.pk in (#place_holder#)
#placeholder# is just a literal place holder. when some one would run the report, #placeholder# is replaced with the literal values from the filter of that report:
select t.pk
from a_table t
where t.pk in (1,2,3,4) -- or whatever the user selects
t.pk is an int
note: doing
declare #t as table (
num int
)
insert into #t values (#Placeholder#)
does not work.
Your description is a bit ridicuolus, but you might give this a try:
Whatever you mean with this
I see what your trying to say; but if I type out '#placeholder#' in the script, I'll end up with '1','2','3','4' and not '1,2,3,4'
I assume this is a string with numbers, each number between single qoutes, separated with a comma:
DECLARE #passedIn VARCHAR(100)='''1'',''2'',''3'',''4'',''5'',''6'',''7''';
SELECT #passedIn; -->: '1','2','3','4','5','6','7'
Now the variable #passedIn holds exactly what you are talking about
I'll use a dynamic SQL-Statement to insert this in a temp-table (declared table variable would not work here...)
CREATE TABLE #tmpTable(ID INT);
DECLARE #cmd VARCHAR(MAX)=
'INSERT INTO #tmpTable(ID) VALUES (' + REPLACE(SUBSTRING(#passedIn,2,LEN(#passedIn)-2),''',''','),(') + ');';
EXEC (#cmd);
SELECT * FROM #tmpTable;
GO
DROP TABLE #tmpTable;
UPDATE 1: no dynamic SQL necessary, all ad-hoc...
You can get the list of numbers as derived table in a CTE easily.
This can be used in a following statement like WHERE SomeID IN(SELECT ID FROM MyIDs) (similar to this: dynamic IN section )
WITH MyIDs(ID) AS
(
SELECT A.B.value('.','int') AS ID
FROM
(
SELECT CAST('<x>' + REPLACE(SUBSTRING(#passedIn,2,LEN(#passedIn)-2),''',''','</x><x>') + '</x>' AS XML) AS AsXml
) as tbl
CROSS APPLY tbl.AsXml.nodes('/x') AS A(B)
)
SELECT * FROM MyIDs
UPDATE 2:
And to answer your question exactly:
With this following the CTE
insert into #t(num)
SELECT ID FROM MyIDs
... you would actually get your declared table variable filled - if you need it later...

TSQL Insert the column default value from Case Statement

I'd like to use the column's default value in an stored procedure insert, so that I don't have to repeat the default value in multiple places (it could change... DRY principle).
The T-SQL INSERT operation has a handy 'default' keyword that I can use as follows:
Declare #newA varchar(10)
Set #newA = 'Foo2'
-- I can use "default" like so...
Insert into Table_1 (
A,
B)
Values (
#newA,
default)
However, If I need to do something conditional, I can't seem to get the case statement to return 'default'.
-- How do I use 'default' in a case statement?
INSERT INTO Table_1 (
A,
B )
VALUES (
#newA,
CASE WHEN (#newA <> 'Foo2') THEN 'bar' ELSE default END)
-- > yeilds "Incorrect syntax near the keyword 'default'."
I could insert the default, and then update as needed like so:
INSERT INTO Table_1 (
A,
B )
VALUES (
#newA,
default)
UPDATE Table_1
SET B = CASE WHEN (A <> 'Foo2') THEN 'bar' ELSE B END
WHERE ID = SCOPE_IDENTITY()
But I'd really like somebody to tell me "There's a better way..."
Here's a table definition for this example if it helps...
CREATE TABLE dbo.Table_1 (
ID int NOT NULL IDENTITY (1, 1),
A varchar(10) NULL,
B varchar(10) NULL )
GO
ALTER TABLE dbo.Table_1 ADD CONSTRAINT DF_Table_1_A DEFAULT 'A-Def' FOR A
GO
ALTER TABLE dbo.Table_1 ADD CONSTRAINT DF_Table_1_B DEFAULT 'B-Def' FOR B
GO
default only works from within a VALUES() block, which does not seem to be an acceptable value in a CASE statement; you could use an if statement to determine what to insert:
DECLARE #newA varchar(10) = 'Foo2'
IF (#newA <> 'Foo2')
BEGIN
INSERT INTO Table_1 (A, B)
SELECT #newA, 'bar'
END
ELSE
BEGIN
--If you are using default values, you do not have to specify the column
INSERT INTO Table_1 (A)
SELECT #newA
END
I think this is better than updating after an insert, so that you only insert correct data into your table. It also keeps the number of INSERTS/UPDATES to 1. You should also be careful when you using ##IDENTITY due to scoping. Consider looking into SCOPE_IDENTITY().