I'm trying to create a temporary table with a select into statement in a stored procedure as follows:
SELECT *
INTO #GENEALOGY
FROM
(
SELECT field1, field2,
(SELECT fieldA from tableY WHERE...) as field3,
(SELECT fieldB from tableY WHERE...) as field4
FROM table
WHERE condition
)
Any command I type after this closing bracket fails the syntax check (such as another SELECT statement).
I've tried putting BEGIN and END before and after the whole statement and then starting my next command.
I've tried adding
AS tablename
after the closing bracket and then the next statement but it doesn't like that either
I've tried removing the # but same problem.
I actually need to run a WHILE loop after this and INSERT more records into the same table.
What am i doing wrong?
thanks
Out of curiosity, why are you using a subquery?
SELECT field1, field2,
(SELECT fieldA from tableY WHERE...) as field3,
(SELECT fieldB from tableY WHERE...) as field4
INTO #GENEAOLOGY
FROM table
WHERE condition;
The structure of your query is ok. You should include a semi-colon at the end, if this is in a programming block. I assume table is a real name and that the other parts of the query are syntactically correct.
What does the error mention? If you run this in SSMS more than once, the second time the temp table already exists and could be an error.
You said an alias was not enough, but this is a right sentence:
SELECT *
INTO #GENEALOGY
FROM
(
SELECT field1, field2,
(SELECT fieldA from tableY WHERE...) as field3,
(SELECT fieldB from tableY WHERE...) as field4
FROM table
WHERE condition
) as TableNameAlias
thanks guys for the help
in the end I changed to an INSERT INTO rather than a SELECT INTO because
a) i needed to do 2 different select queries to get the data i need (1 for the first record and a 2nd for all subsequent records) and the second query would have had to be an INSERT anyway
b) and i wasn't sure how long sql server would keep the temp table open if i was calling the procedure from a crystal report
so i created a fixed table, use SELECT INTO and just delete all records as first line of my sp to clear out unwanted data
ta!
Related
Using MS Access, via VBA, I have been trying to update an main Access database table from an identically structured external Access database table. Same columns, same fields. The external databases are used to update a central main database.
What I have been trying to develop is a line of SQL that only appends the entries that are completely unique. Because there is no foreign keys or unique identifiers for the incoming data that can be referenced, I am required to check each field to make sure that there are no exact duplicates. So, if the table had 2 fields, if entries failed the logic test
intTable.field1 = extTable.field1 And intTable.field2 = extTable.field2
then those are the entries that would be appended.
The code I came up with is below, and when it runs it tries to append (in a Gary Oldman voice) EVERYTHING. I can't find out what could be wrong with it, as it's almost like it ignores the WHERE or WHERE NOT EXIST. I have tried dozens of small edits and alternate versions. Either is appends all or none.
INSERT INTO Table1
SELECT field1, field2, field3, field4, field5
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB
WHERE NOT EXISTS (SELECT *
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB1
WHERE ('Table1.[field1]'='sourceDB1.[field1]' And
'Table1.[field2]'='sourceDB1.[field2]' And
'Table1.[field3]'='sourceDB1.[field3]' And
'Table1.[field4]'='sourceDB1.[field4]' And
'Table1.[field5]'='sourceDB1.[field5]'));
FINAL CODE (after implementing ArcherBird's solution):
INSERT INTO Table1
SELECT field1, field2, field3, field4, field5
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB
WHERE NOT EXISTS (SELECT *
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB1
WHERE ((sourceDB.[field1] = sourceDB1.[field1] Or (sourceDB.[field1] IS NULL And sourceDB1.[field1] IS NULL)) And
(sourceDB.[field2] = sourceDB1.[field2] Or (sourceDB.[field2] IS NULL And sourceDB1.[field2] IS NULL)) And
(sourceDB.[field3] = sourceDB1.[field3] Or (sourceDB.[field3] IS NULL And sourceDB1.[field3] IS NULL)) And
(sourceDB.[field4] = sourceDB1.[field4] Or (sourceDB.[field4] IS NULL And sourceDB1.[field4] IS NULL)) And
(sourceDB.[field5] = sourceDB1.[field5] Or (sourceDB.[field5] IS NULL And sourceDB1.[field5] IS NULL)) ));
1) Remove the string quotes from your field comparison logic.
2) You have aliased Table1 in your query as sourceDB, so use that reference.
3) The table where you check for non-existence ought to be the "local" version of Table1 (the one you are inserting into).
INSERT INTO Table1
SELECT field1,
field2,
field3,
field4,
field5
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB
WHERE NOT EXISTS (SELECT *
FROM [Table1] sourceDB1
WHERE (sourceDB.[field1] = sourceDB1.[field1] And
sourceDB.[field2] = sourceDB1.[field2] And
sourceDB.[field3] = sourceDB1.[field3] And
sourceDB.[field4] = sourceDB1.[field4] And
sourceDB.[field5] = sourceDB1.[field5]));
EDIT:
To deal with the case where these fields might have null values, you cannot do a simple = comparison since null does not equal null. The best way I can think of to get around this in MS Access would be to replace null with some other value that is not likely to be used. In doing so, you also need to make sure you chose replacement values that are consistent with the data type. I will make an assumption that all your fields are text.
INSERT INTO Table1
SELECT field1,
field2,
field3,
field4,
field5
FROM [;DATABASE=C:\extDB.accdb].[Table1] sourceDB
WHERE NOT EXISTS (SELECT *
FROM [Table1] sourceDB1
WHERE (nz(sourceDB.[field1],"!##") = nz(sourceDB1.[field1],"!##") And
nz(sourceDB.[field2],"!##") = nz(sourceDB1.[field2],"!##") And
nz(sourceDB.[field3],"!##") = nz(sourceDB1.[field3],"!##") And
nz(sourceDB.[field4],"!##") = nz(sourceDB1.[field4],"!##") And
nz(sourceDB.[field5],"!##") = nz(sourceDB1.[field5],"!##")));
I have a table with 2001233 records.
I can use 'Select distinct * from that_table' to get all records not repeated.
Maybe about 2001100 records.
How to get those 133 records into another table if I want to check the records disappeared after 'distinct'.
Another question is
When appending new records from one table to another table, how to check that the appended record is not already in the target table?
thanks for answering my question :)
It would be a hack and slow for 2+ million rows but you can do this:
Select Sys(2017,'',0,3) As crc, * ;
from myTable Into Cursor crsTemp ;
nofilter
Select * From crsTemp ;
where crc In ;
( Select crc From crsTemp;
having Count(*) > 1 ;
group By crc) ;
into Cursor crsDupes ;
nofilter
Select crsDupes
Browse
You should have used primary key from the start.
For your second question, I think it is best to use "insert into" rather than append. i.e.:
Insert into tableA ;
select * from tableB t1 ;
where not exists ( ;
select * from tableA t2 ;
where t1.field1 = t2.field1 and t1.field2 = t2.field2)
Here is another way to find the duplicate records:
Assuming that you don't keep deleted records hanging around...
select tableA
set deleted off
delete all
index on <key expression> to keyfield unique
set deleted on
recall all
browse for deleted
This process will delete all the records, and the recall statement will only apply to the indexed records, leaving the duplicates tagged as deleted.
Try this to check if there is a duplicate record.
SELECT colName, count(*) FROM tblName GROUP BY colName HAVING count(*) > 1
I'm trying to append two tables in MS Access at the moment. This is my SQL View of my Query at the moment:
INSERT INTO MainTable
SELECT
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Where "University" is the only field name that would have similarities between the two tables. When I try and run the query, I get this error:
Query must have at least one destination field.
I assumed that the INSERT INTO MainTable portion of my SQL was defining the destination, but apparently I am wrong. How can I specify my destination?
You must select something from your select statement.
INSERT INTO MainTable
SELECT col1, col2
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Besides Luke Ford's answer (which is correct), there's another gotcha to consider:
MS Access (at least Access 2000, where I just tested it) seems to match the columns by name.
In other words, when you execute the query from Luke's answer:
INSERT INTO MainTable
SELECT col1, col2
FROM ...
...MS Access assumes that MainTable has two columns named col1 and col2, and tries to insert col1 from your query into col1 in MainTable, and so on.
If the column names in MainTable are different, you need to specify them in the INSERT clause.
Let's say the columns in MainTable are named foo and bar, then the query needs to look like this:
INSERT INTO MainTable (foo, bar)
SELECT col1, col2
FROM ...
As other users have mentioned, your SELECT statement is empty. If you'd like to select more that just col1, col2, however, that is possible. If you want to select all columns in your two tables that are to be appended, you can use SELECT *, which will select everything in the tables.
Icurrently have in my database (SQL server 2005 Express) 2 tables, tblDepartment and tblDepartmentcola. The difference between the two is that "cola" has an additional boolean field. For reasons beyond the scope of this question, i need to insert any changes made to tblDepartment in tblDepartmentcola. For that i need to use a trigger.
After reading some stuff, i got the impression that a temporary "updated" table does not exist? is this right?. If so, how could i select the "updated" row?, i have made triggers in the past making selects from "updated" and "Deleted" tables, but this one does not work. any idea why?
CREATE TRIGGER items_ ON [tblDepartment] FOR Update AS
INSERT INTO [tblDepartmentcola]
SELECT ...
go
there's no updated table in Sql server, only inserted and deleted
CREATE TRIGGER items_ ON [tblDepartment] after Update AS
begin
INSERT INTO [tblDepartmentcola]
SELECT * from inserted
end
If you want to see the records that were updated to insert into a different table you can query the INSERTED table within a trigger when the primary key exists within the DELETED table.
INSERT INTO TrackUpdatesTable ( PrimaryFieldId, Field1, Field2, Field3 )
SELECT I.PrimaryFieldId, I.Field1, I.Field2, I.Field3
FROM INSERTED I
JOIN DELETED D ON D.PrimaryFieldId = I.PrimaryFieldId
or
INSERT INTO TrackUpdatesTable ( PrimaryFieldId, Field1, Field2, Field3 )
SELECT I.PrimaryFieldId, I.Field1, I.Field2, I.Field3
FROM INSERTED I
WHERE EXISTS ( SELECT * FROM DELETED WHERE PrimaryFieldId = I.PrimaryFieldId )
Hope this helps.
I want to produce a map that contains the original room ID and its new room ID equivalent for every room created.
Try using the "OUTPUT" clause with your insert statement. You can then map all of the inserted values and the keys that went with it to a different "mapping" table. Edit: I should add, this is all done in a SINGLE transaction, which makes the performance GREAT!
Insert Into TableA
(
Field1,
Field2,
Field3
)
Output Inserted.Field1, Field2, Field3, MappingID
Into MappingTable
Select Field1, Field2, Field3
From Rooms
Here's a link to the msdn site for the OUTPUT clause: http://msdn.microsoft.com/en-us/library/ms177564.aspx
Though I would suggest you to alter the table design and have a separate column each for New and Original site Id, but in present design I think you are looking for following:
SELECT
Name, #origSiteID, ControlsSiteNum, ControlsRoomNum, IsActive
FROM Rooms
WHERE SiteID = #newSiteID