I am using SQL Server 2012 and I have 2 tables with the following definition
CREATE TABLE t1 (id INT PRIMARY KEY, value NVARCHAR(10))
CREATE TABLE t2 (id INT PRIMARY KEY, value BIT DEFAULT 1)
ALTER TABLE t2 WITH CHECK ADD CONSTRAINT FK FOREIGN KEY(id) REFERENCES t1 (id)
I inserted the following columns for the current example:
INSERT INTO t1 VALUES (1, 'a')
INSERT INTO t1 VALUES (2, 'b')
INSERT INTO t1 VALUES (3, 'c')
INSERT INTO t2 VALUES (1, 1)
INSERT INTO t2 VALUES (3, 0)
I am running this query and it works
SELECT
t1.*, ISNULL(t2.value, 1)
FROM
t1
LEFT JOIN t2 ON t1.id = t2.id
Is there any way to replace the 1 in this part ISNULL(t2.value, 1) with the default value that I have defined in the column value in the table t2?
Here is the sqlfiddle I created with this example: SQLFIDDLE DEMO
UPDATE 1:
I can't use SQL Server: Find out default value of a column with a query because it returns ((1)) and I can't cast ((1)) to BIT.
Is there any way to fix that?
You are not using the default in the manner it is intended. It is something SQL Server evaluates internally at time of insert (or potentially update if the default keyword is used).
It is not intended for use in SELECT. Consider that it can contain arbitrary expressions such as DEFAULT CAST(GETDATE() AS INT) % 2 or calling a Scalar UDF. Casting from string to bit won't evaluate those expressions for you.
The only way you could do something like this would be to evaluate it separately
DECLARE #B BIT
, #Definition NVARCHAR(max)
SELECT #Definition = N'SELECT #B = '
+ object_definition(default_object_id)
FROM sys.columns
WHERE NAME = 'value'
AND object_id = OBJECT_ID('dbo.t2')
EXEC sys.sp_executesql
#Definition,
N'#B BIT OUTPUT',
#B = #B OUTPUT
SELECT t1.*,
ISNULL(t2.value, #B)
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
This works for me:
DECLARE #def as bit = null
SELECT #def
UNION ALL
SELECT ISNULL(#def, REPLACE(REPLACE((
SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'dual'
AND COLUMN_NAME = 'tempo'),'(', ''), ')', '')) As def
Related
I need to do something like this:
SET #MyTableAsArgument = 'Foo;Bar\n1;2\n3;4\n'; -- CSV or any other table-format
SET #AnOtherArgument = 'somedata';
SELECT * FROM table1 t1, #MyTableAsArgument t2
WHERE t1.foo = t2.foo
AND t1.bar = #AnOtherArgument
Is there a way to do this?
The only other solution I see is:
Create a temporary table tmp1
Insert my MyTableAsArgument to the tmp1
Do My query on table1 and tmp1
Delete my temporary table tmp1
I am not sure if this is an abuse of temporary tables.
Is there a significant performance overhead with temporary tables as they are used for queries?
Can you use a table variable or temporary table?
DECLARE #MyTable TABLE (foo VARCHAR(255));
INSERT INTO #MyTable (foo)
VALUES ('Foo'), ('Bar\n12\n3'), ('4\n');
SET #AnOtherArgument = 'somedata';
SELECT t1.*
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM #MyTable) AND
t1.bar = #AnOtherArgument;
If this is not possible, you can use a SPLIT() functions -- STRING_SPLIT() is built into the most recent versions -- but other versions are on the web:
SELECT *
FROM table1 t1
WHERE t1.foo IN (SELECT foo FROM string_split(#MyTableLIST, ';') ss(foo)) AND
t1.bar = #AnOtherArgument;
#Cosinus, there is a temp table variable too in SQL. This allows you to define the columns you want in that table and using a 'union all' you can insert elements in that table.
See this mockup below.
DECLARE #MyTableAsArgument table(Name varchar(20), foo varchar(50), descb varchar(100), pj_id int)
DECLARE #AnOtherArgument varchar(20) = 'somedata';
INSERT into #MyTableAsArgument
SELECT 'James', 'iphone', 'cell phone', 1 union all
SELECT 'Michael', 'macbook', 'laptop', 2 union all
SELECT 'Henry', 'windows', 'os', 3
SELECT *
FROM
table1 t1
Join #MyTableAsArgument t2 ON
t1.foo = t2.foo
AND
t1.bar = #AnOtherArgument
I want to update each row of table1->keyField based on table2 value
Table1
Id|keyField
1|test_500
2|test_501
3|test_501
500,501 are primary key of and my another table2
Table2
Id|value
500|A
501|B
502|C
I have tried something like
update table1 set keyField=(select value from table2 where id=substring(expression))
but my select return multiple statement so unable to run the query.
any help or direction please?
You can use the syntax like this
UPDATE table1 SET keyField = Table2.Value
FROM table1 INNER JOIN table2
ON table1.Id = substring(expression))
If I get it right, this might be what you need:
UPDATE T1 SET
keyField = T2.Value
FROM
Table1 AS T1
INNER JOIN Table2 AS T2 ON T2.id = SUBSTRING(T1.keyField, 6, 100)
Careful when comparing substring result with an numeric value, might get a conversion error.
Try this code (necessary notes are in comments below):
--generate some sample data (the same as you provided)
declare #table1 table (id int, keyField varchar(10))
insert into #table1 values (1,'test_500'),(2,'test_501'),(3,'test_502')
declare #table2 table (id int, value char(1))
insert into #table2 values (500,'A'),(501,'B'),(502,'C')
--in case you want to see tables first
--select * from #table1
--select * from #table2
--here you extract the number in first table in keyField column and match it with ID from second table, upon that, you update first table
update #table1 set keyField = value from #table2 [t2]
where cast(right(keyfield, len(keyfield) - charindex('_',keyfield)) as int) = [t2].id
select * from #table1
Table A has columns 1 and 2.
Column 1's value must be unique if column 2 is equal to x.
ALTER TABLE A
ADD UNIQUE (1) WHERE 2 = x.
But this gives me a syntax error near WHERE.
I tried to create an index, but I can't figure out how to make that do what I want either.
Create unique nonclustered index [my_index]
on [TableA]([1])
where [2] = x
Here's an alternative solution using a Function although the index is a better solution:
CREATE FUNCTION dbo.CheckConstraint
(
#col1 int,
#col2 CHAR(1)
)
RETURNS INT
AS
BEGIN
DECLARE #ret INT
SELECT #ret = COUNT(*)
FROM YourTable
WHERE col1 = #col1 AND #col2 = 'X'
RETURN #ret
END;
CREATE TABLE YourTable (col1 int, col2 char(1));
ALTER TABLE YourTable
ADD CONSTRAINT CheckForXConstraint CHECK (NOT (dbo.CheckConstraint(col1,col2) > 1));
INSERT INTO YourTable VALUES (1, 'X');
INSERT INTO YourTable VALUES (2, 'X');
INSERT INTO YourTable VALUES (2, 'Y');
INSERT INTO YourTable VALUES (2, 'X'); <-- This line fails
SQL Fiddle Demo
Okay the title cannot explain the situation correct enough.
Now this is it,
I have a table with columns
Table1
Columns0, CHAR(20), NOT NULL.
Columns1, CHAR(4), Allow Nulls.
Data : 'ARR '
Table2
Columns0, CHAR(20), NOT NULL.
Columns1, CHAR(4), NOT NULL.
Data : 'ARR '
Then I join two tables together.
SELECT (ISNULL(a.Columns1,'') + ISNULL(b.Columns1,'')) AS WhatEver
FROM Table1 a
left join Table2 b on a.Columns0 = b.Columns0
The result should appear as 'ARR ARR '
instead of this, it appear as 'ARRARR '
Why does this happen?
EDIT 2012/06/11:
After struggling, I ended up doing things like:
SELECT ISNULL(CONVERT(CHAR(4),a.Columns1),'') + ISNULL(b.Columns1,'')
Then only I get correct result 'ARR ARR '
But I am pretty sure my data type is CHAR(4) in the database.
Thank guys..
EDIT 2012/08/06:
Another solution that I found working is to change the TABLE 2 COLUMN 1 to (CHAR(4), NULL).
This can be done through
ALTER TABLE [table_name] MODIFY [column_name] [column_data_type] [null|not null]
Your example works fine on my server (SQL Server 2008 R2):
create table SOxx1
(
col1 char(4),
col2 char(20) not null
)
create table SOxx2
(
col1 char(4),
col2 char(20) not null
)
Go
insert into SOxx1 (col1, col2) VALUES ('ARR ', 'abc')
insert into SOxx2 (col1, col2) VALUES ('ARR ', 'abc')
go
SELECT (ISNULL(a.col1,'') + ISNULL(b.col1,'')) AS WhatEver
FROM SOxx1 a
left join SOxx2 b on a.Col2 = b.Col2
-- OUTPUT is 'ARR ARR '
Are you sure your columns are CHAR and not VARCHAR?
Nothing is stripping spaces after you get the result from SQL Server?
Can you try this:
declare #table1 table (id int, one char(4))
declare #table2 table (id int, one char(4))
insert into #table1 values (1 ,'ARR ')
insert into #table2 values (1 ,'ARR ')
select (isnull(a.one,'') + isnull(b.one,'')) AS WhatEver
from #table1 a left join #table2 b on a.id = b.id
I get, as expected,
ARR ARR
Have you tried different collations?
SELECT ISNULL(a.Columns1,'') collate Latin1_General_BIN + ISNULL(b.Columns1,'') collate Latin1_General_BIN AS WhatEver
FROM Table1 a
left join Table2 b on a.Columns0 = b.Columns0
SELECT (ISNULL(a.Columns1,'') +ISNULL(b.Columns1,'')) AS WhatEver FROM Table1 a left join Table2 b on a.Columns0 = b.Columns0
I tried to perform the following in order to update a psuedo-identity value at the same time as using the value to create new rows, but APPLY does not like UPDATE statements as the right table source. What's the most elegant alternative outside of simply using an identity column?
create table Temp1(
id int not null identity(1,1) primary key
,data nvarchar(max) null)
create table Temp2(
id int not null primary key
,fkTemp1 int not null references Temp1(id)
,data nvarchar(max) null)
create table Numbering(
ObjectCode int not null primary key
,AutoKey int)
insert into Temp1(data) values('test string')
insert into Temp1(data) values('another test string')
insert into Numbering(ObjectCode, AutoKey) values(4, 1)
insert into Temp2(id, fkTemp1, data)
select n.AutoKey, t1.id, t1.data
from Temp1 t1
left join Temp2 t2 on t2.fkTemp1 = t1.id
cross apply (update Numbering set AutoKey = AutoKey + 1 output inserted.AutoKey where ObjectCode = 4) n
where t2.id is null -- only insert where a target row does not already exist
You cannot do an INSERT and UPDATE on two different tables in one statement in SQL Server 2005.
In SQL Server 2008 there is MERGE construct, however, it works only on single table.
Just run two statements in a transaction:
BEGIN TRANSACTION
DECLARE #AutoKey INT
SELECT #AutoKey = AutoKey
FROM Numbering WITH (UPDLOCK)
WHERE ObjectCode = 4
INSERT
INTO temp2
SELECT #AutoKey + ROW_NUMBER() OVER (ORDER BY id), id, data
FROM temp1
WHERE id NOT IN
(
SELECT fkTemp1
FROM temp2
)
UPDATE Numbering
SET AutoKey = AutoKey + ##ROWCOUNT
WHERE ObjectCode = 4
COMMIT
Update:
As #Remus Rusanu pointed out, you actually can pipeline UPDATE output clause into a table in SQL Server 2005.
However, it seems you can neither JOIN nor CROSS APPLY the OUTPUT resultset to the result of other queries.
This will do it, but you'll have to fix the "T2.ID IS NULL" problem...
Declare #Key as int
Declare #cnt as int
Begin Transaction
Set #cnt = (Select count(*)
from Temp1 t1 left join Temp2 t2 on t2.fkTemp1 = t1.id
--where t2.id is null -- note: does not work, not sure what is intended
)
update Numbering set #Key = AutoKey = AutoKey + #cnt where ObjectCode = 4
insert into Temp2(id, fkTemp1, data)
select #Key+ROW_NUMBER() over (Order By t1.id)
, t1.id, t1.data
from Temp1 t1
left join Temp2 t2 on t2.fkTemp1 = t1.id
--where t2.id is null -- note: does not work,
Commit Transaction