SQL Server 2005 - Insert with Select for 1 Value - sql

Basically I have 2 tables but the problem is I would like to insert data from table A column A to table B column C.
But when I try to this I get an error
My subquery is:
SELECT TOP 1 [Id]
From [A]
Where [B] = 'ValueCon'
And here is my insert query
INSERT INTO [B]
([BA]
,[BB]
)
VALUES
('TestData'
,(SELECT TOP 1 [Id]
From [A]
Where [AB] = 'ValueCon')
)
There is no need to worry about data types as they are all matching.
I get the following error:
Subqueries are not allowed in this context. Only scalar expressions are allowed.
I have seen many complex ways of getting around this but just need something simple.

May be if you use a declared param, you can use it to the INSERT
DECLARE #theInsertedId INT;
SELECT TOP 1 #theInsertedId=[Id]
From [A]
Where [B] = 'ValueCon'
INSERT INTO [B]
([BA]
,[BB]
)
VALUES
('TestData'
,#theInsertedId
)
Sorry for by bad english! Hope this help!

Read up on the proper syntax for INSERT! It's all very well documented in the SQL Server Books Online ....
Either you have INSERT and VALUES and you provide atomic values (variables, literal values), e.g.
INSERT INTO [B] ([BA], [BB])
VALUES ('TestData', #SomeVariable)
OR you're using the INSERT ... SELECT approach to select column from another table (and you can also mix in literal values), e.g.
INSERT INTO [B] ([BA], [BB])
SELECT
TOP 1 'TestData', [Id]
FROM [A]
WHERE [AB] = 'ValueCon'
but you cannot mix the two styles. Pick one or the other.

You could just have a single select statement?
Not sure if this will work for what you are trying to do....
declare #a table
(
ab varchar(20),
id varchar(20)
)
insert #a
select 'ValueCon',1
union all
select 'ValueCon',2
union all
select 'Con',100
declare #b table
(
ba varchar(20),
bb varchar(20)
)
insert #b (ba,bb)
select top 1 'TestData',id from #a where ab='Valuecon'
select * from #a
select * from #b

Related

SQL: UPDATE many-to-many's intermediate table

I have table A and table B. Relation between them done using intermediate table AB, which stores ID's from both.
Table A
ID integer
Value varchar(MAX)
Table B
ID integer
Value varchar(MAX)
Table AB
AID integer
BID integer
I can select needed data with JOIN's, but how to write data into AB?
I mean if I'll get AID and list of integer's (done as custom type Array_Integer table(ID integer)) , which is BID, how to update relations in AB with a received list of BID's?
I can do a lot of dirty and manually work, but I'm looking for a more true way.
UPD: check schema on pastebin — http://pastebin.com/BeKm2h3F
If I understand you correct, this query should be what you need.
INSERT INTO AB
SELECT * FROM
(
-- Here you write your AID value instead of 1
SELECT 1 AS AID
) AS a1
CROSS JOIN
(
-- Query that returns list if id's from table B
SELECT ID AS BID FROM B WHERE ID < 5
)
You can update the TableAB as follows :
declare #Aid int
declare #Bid int
insert into TableA(value)
select 'abcd'
set #Aid = ident_currect('TableA')
insert into TableB(value)
select 'xyz'
set #Bid = ident_currect('TableB')
insert into TableAB -- This will update your junction table
select #Aid,#Bid
I am assuming that your tableA and TableB have identity columns. You can also use scope_identity() instead of ident_currect()

How do I return the column name in table where a null value exists?

I have a table of more than 2 million rows and over 100 columns. I need to run a query that checks if there are any null values in any row or column of the table and return an ID number where there is a null. I've thought about doing the following, but I was wondering if there is a more concise way of checking this?
SELECT [ID]
from [TABLE_NAME]
where
[COLUMN_1] is null
or [COLUMN_2] is null
or [COLUMN_3] is null or etc.
Your method is fine. If your challenge is writing out the where statement, then you can run a query like this:
select column_name+' is null or '
from information_schema.columns c
where c.table_name = 'table_name'
Then copy the results into a query window and use them for building the query.
I used SQL Server syntax for the query, because it looks like you are using SQL Server. Most databases support the INFORMATION_SCHEMA tables, but the syntax for string concatenation varies among databases. Remember to remove the final or at the end of the last comparison.
You can also copy the column list into Excel and use Excel formulas to create the list.
You can use something similar to the following:
declare #T table
(
ID int,
Name varchar(10),
Age int,
City varchar(10),
Zip varchar(10)
)
insert into #T values
(1, 'Alex', 32, 'Miami', NULL),
(2, NULL, 24, NULL, NULL)
;with xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' as ns)
select ID,
(
select *
from #T as T2
where T1.ID = T2.ID
for xml path('row'), elements xsinil, type
).value('count(/row/*[#ns:nil = "true"])', 'int') as NullCount
from #T as T1

How to scan for differences between two queries?

I have a table that loads new data every day and another table that contains a history of changes to that table. What's the best way to check if any of the data have changed since the last time data was loaded?
For example, I have table #a with some strategies for different countries and table #b tracks the changes made to table #a. I can use a checksum() to hash the fields that can change, and add them to the table if the existing hash is different from the new hash. However, MSDN doesn't think this is a good idea since "collisions" can occur, e.g. two different values map to the same checksum.
MSDN link for checksum
http://msdn.microsoft.com/en-us/library/aa258245(v=SQL.80).aspx
Sample code:
declare #a table
(
ownerid bigint
,Strategy varchar(50)
,country char(3)
)
insert into #a
select 1,'Long','USA'
insert into #a
select 2,'Short','CAN'
insert into #a
select 3,'Neutral','AUS'
declare #b table
(
Lastupdated datetime
,ownerid bigint
,Strategy varchar(50)
,country char(3)
)
insert into #b
(
Lastupdated
,ownerid
,strategy
,country
)
select
getdate()
,a.ownerid
,a.strategy
,a.country
from #a a left join #b b
on a.ownerid=b.ownerid
where
b.ownerid is null
select * from #b
--get a different timestamp
waitfor delay '00:00:00.1'
--change source data
update #a
set strategy='Short'
where ownerid=1
--add newly changed data into
insert into #b
select
getdate()
,a.ownerid
,a.strategy
,a.country
from
(select *,checksum(strategy,country) as hashval from #a) a
left join
(select *,checksum(strategy,country) as hashval from #b) b
on a.ownerid=b.ownerid
where
a.hashval<>b.hashval
select * from #b
How about writing a query using EXCEPT? Just write queries for both tables and then add EXCEPT between them:
(SELECT * FROM table_new) EXCEPT (SELECT * FROM table_old)
The result will be the entries in table_new that aren't in table_old (i.e. that have been updated or inserted).
Note: To get rows recently deleted from table_old, you can reverse the order of the queries.
There is no need to check for changes if you use a different approach to the problem.
On your master table create a trigger for INSERT, UPDATE and DELETE which tracks the changes for you by writing to table #b.
If you search the internet for "SQL audit table" you will find many pages describing the process, for example: Adding simple trigger-based auditing to your SQL Server database
Thanks to #newenglander I was able to use EXCEPT to find the changed row. As #Tony said, I'm not sure how multiple changes will work, but here's the same sample code reworked to use Except instead of CHECKSUM
declare #a table
(
ownerid bigint
,Strategy varchar(50)
,country char(3)
)
insert into #a
select 1,'Long','USA'
insert into #a
select 2,'Short','CAN'
insert into #a
select 3,'Neutral','AUS'
declare #b table
(
Lastupdated datetime
,ownerid bigint
,Strategy varchar(50)
,country char(3)
)
insert into #b
(
Lastupdated
,ownerid
,strategy
,country
)
select
getdate()
,a.ownerid
,a.strategy
,a.country
from #a a left join #b b
on a.ownerid=b.ownerid
where
b.ownerid is null
select * from #b
--get a different timestamp
waitfor delay '00:00:00.1'
--change source data
update #a
set strategy='Short'
where ownerid=1
--add newly changed data using EXCEPT
insert into #b
select getdate(),
ownerid,
strategy,
country
from
(
(
select
ownerid
,strategy
,country
from #a changedtable
)
EXCEPT
(
select
ownerid
,strategy
,country
from #b historicaltable
)
) x
select * from #b

INSERT INTO With a SubQuery and some operations

I'm trying to insert some data to a table contains two things : "a string" and "maximum number in Order column + 1".
This is my query:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (Max([Order]) + 1)
FROM MyTable
What is going wrong with my query?
I'm using Microsoft SQL Server 2005 SP3.
You can test this query like this:
I don't receive error:
create table #MyTable
(
[Text] varchar(40),
[Order] int NOT NULL
)
INSERT INTO #MyTable([Text],[Order])
SELECT 'MyText' [Text], isnull(max([order]) + 1, 0) [Order]
FROM #MyTable
drop table #MyTable
Original:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
or
INSERT INTO MyTable ([Text],[Order])
SELECT top 1 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
limit is not valid in SQL Server as far as I know.
Cannot insert the value NULL into column 'Order', table 'master.dbo.MyTable'; column does not allow nulls. INSERT fails. The statement has been terminated.
This means that the Order column isn't allowed to be null, and that the Max([Order]) + 1 part of your column returns NULL.
This is because your table is empty, as you already noticed by yourself.
You can work around this by replacing NULL by a real number in the query, using ISNULL():
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (isnull(Max([Order]),0) + 1)
FROM MyTable
Unless he has a column named OrderBy
then he would have to add / assign all values within that Insert especially if the column does not allow for nulls
sounds like fully qualifying the Insert with the dbo.MyTable.Field may make more sense.
also why are you naming fields with SQL Key words...???
INSERT INTO MyTable ([Text],[Order] Values('MyTextTest',1)
try a test insert first..

how to change this sql query

SELECT *
FROM dbo.tbh_table
WHERE TopicID IN (
SELECT value
FROM dbo.fn_split('19,',')
)
I have to change above query to execute result like below
SELECT *
FROM dbo.tbh_table
WHERE TopicID LIKE '%19,%'
My topicID values are like this 15,19,12,1
But split will give values are 15 19 12 1. because of which i am not able to execute the query.
any guidance will help
Assuming that fn_split is a table valued function (TVF), returning a TABLE (value INT), use this:
SELECT t.*
FROM dbo.tbh_table t
CROSS APPLY
dbo.fn_split(TopicID) split
WHERE split.value = 19
You could add your IDs to a table variable and then join with the table variable to determine if TopicID was in the table variable.
DECLARE #DesiredIDs TABLE (
DesiredID INT
)
INSERT INTO #DesiredIDs (DesiredID) Values (15)
INSERT INTO #DesiredIDs (DesiredID) Values (19)
INSERT INTO #DesiredIDs (DesiredID) Values (12)
INSERT INTO #DesiredIDs (DesiredID) Values (1)
select * from tbh_table t
left join #DesiredIDs d on d.DesiredID = t.TopicID
where d.DesiredID is not null
If I understand your question correctly, you want something like this:
SELECT *
FROM dbo.tbh_table
WHERE 19 IN (
SELECT value
FROM dbo.fn_split(TopicId,',')
)