How can I alter a temp table? - sql

I need to create a temp table, than add a new int NOT NULL AUTO_INCREMENT field to it so I can use the new field as a row number. Whats wrong with my query?
SELECT post, newid FROM ((SELECT post`test_posts`) temp
ALTER TABLE temp ADD COLUMN newid int NOT NULL AUTO_INCREMENT)
edit:
SELECT post, newid FROM ((SELECT post, newid as int NOT NULL AUTO_INCREMENT FROM `test_posts`) temp
This didn't work ether.

Not that this means it's impossible, but I haven't seen any SQL version that will allow you to modify a table from within a SELECT. Pull the alter table out and make it a separate statement. After you fix any syntax issues, you should be good.
Also, it doesn't look like you actually have a "temp table" to alter. Rather, you're looking for a solution that will let you add an arbitrary id to the result of your "SELECT post..." query. I don't know which engine you're using, but a sequence counter, rowid, rownum, or other similar feature would better fit your needs.

If you need a row number and don't want to actually create a temporary table, you can achieve it by using user variables.
SET #my_row_num =0;
SELECT #my_row_num := #my_row_num+1 as row_number, post, newid FROM ((SELECT post`test_posts`) temp;

Related

SQL Server - how to update the ID column after inserting new records

I need to update a SQL Server table periodically by inserting new records into it.
The table has an ID column in the form of Company0001 through Company0020 right now.
Let's say I added one record of a new company into the table. I want to fill the ID column with Company0021 for this new record. Can anyone suggest a way to do this?
Thank you so much!
I would strongly suggest to use an identity column. Identity is a mechanism designed and used for this actual purpose and therefore it would be much better in terms of performance.
Nevertheless, if you insist on IDs on the format 'CompanyXXX' I would suggest to use a varchar column. Then you would add a trigger on the insert and update operations. When the trigger runs, it would find out the last 'CompanyXXX' and form the new one. If you need help regarding triggers, you could check this tutorial.
Hope I helped!
My suggestion would be to have an autoincrement field, and then concatenate the company name with the ID.
If you don't want to do it with an ID field, do you want it to happen automatically, or are you going to manage it manually? If automatically, you'll need to write a trigger to intercept the INSERT and change the value there. Shouldn't be too hard to do.
I'd seriously recommend NOT doing this and going down the autoincrement field path. It's better.
Add another column to the table to hold an integer value (in this example SNo) and then write query as
declare #SNo int
select #SNo=max(SNo)+1 from Table_Name
insert into Table_Namevalues (#SNo,'company'+right('0000'+cast(#SNo as varchar(10)),4))
And then see the result
Hope this helps
In case a solution is required as, having only one column with values in desired format you can create a function as:
create table table1(id varchar(100));
Go
create function dbo.fn_GetCompanyIdentity ()
returns varchar(100)
as
begin
declare #CompanyIdentify varchar(100);
select #CompanyIdentify =
(select 'Company' +
right ('00000' + cast (
(
(
case when Not exists (select ROW_NUMBER() over( order by (select 1)) from Table1 ) then 1
else (select top 1 ROW_NUMBER() over( order by (select 1)) as currentRownumber from Table1 order by currentRownumber desc) + 1
end
)
)
as varchar(4))
,4));
return #CompanyIdentify;
end;
go
and then use the function in insert statement as :
insert into Table1 (id)
select dbo.fn_GetCompanyIdentity();
Go
Hope this helps!!
Why dont you just create an auto-increment column and then concatenate "Company" to this column in another column. And for presentation just select "Company+autoincrement" column.

SQL - Inserting a row and returning primary key

I have inserted a row with some data in a table where a primary key is present. How would one "SELECT" the primary key of the row one just inserted?
I should have been more specific and mentioned that I'm currently
using SQLite.
For MS SQL Server:
SCOPE_IDENTITY() will return you the last generated identity value within your current scope:
SELECT SCOPE_IDENTITY() AS NewID
For SQL Server 2005 and up, and regardless of what type your primary key is, you could always use the OUTPUT clause to return the values inserted:
INSERT INTO dbo.YourTable(col1, col2, ...., colN)
OUTPUT Inserted.PrimaryKey
VALUES(val1, val2, ....., valN)
SQL Server:
You can use ##IDENTITY. After an insert statement, you can run:
select ##identity
This will give you the primary key of the record you just inserted. If you are planning to use it later, I suggest saving it:
set #MyIdentity = ##identity
If you are using this in a stored procedure and want to access it back in your application, make sure to have nocount off.
For MySQL, use LAST_INSERT_ID()
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
You should also be able to start a transaction, insert the row, and select the row using some field that has a unique value that you just inserted, like a timestamp or guid. This should work in pretty much any RDBMS that supports transactions, as long as you have a good unique field to select the row with.
If you need to retrieve the new index in MS SQL when there are triggers on the table then you have to use a little workaround. A simple OUTPUT will not work. You have to do something like this (in VB.NET):
DECLARE #newKeyTbl TABLE (newKey INT);
INSERT INTO myDbName(myFieldName) OUTPUT INSERTED.myKeyName INTO #newKeyTbl VALUES('myValue'); " & _
SELECT newKey FROM #newKeyTbl;"
If using .NET, then the return value from this query can be directly cast to an integer (you have to call "ExecuteScalar" on the .NET SqlCommand to get the return).
For SQLite:
SELECT [Column_1], [Column_2],... [Column_n]
FROM [YourTable]
WHERE rowid = (SELECT last_insert_rowid())
whereas:
Column_1, Column_2,... Column_n: are the primary key of YourTable.
If you'd created YourTable with primary key replaced rowid (i.e. one column pk defined as INTEGER PRIMARY KEY) you just use:
SELECT last_insert_rowid()
Which is a common case.
Finally, this wont work for WITHOUT_ROWID tables.
Please Check:
https://www.sqlite.org/lang_corefunc.html#last_insert_rowid
For PostgreSQL,
INSERT INTO tablename (col1, col2, ...)
VALUES (val1, val2, ...)
RETURNING idcol;
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed.
https://www.postgresql.org/docs/current/sql-insert.html
For Postgresql:
SELECT CURRVAL(pg_get_serial_sequence('schema.table','id'))
Source: PostgreSQL function for last inserted ID
select MAX(id_column) from table
That, in theory, should return you that last inserted id. If it's a busy database with many inserts going on it may not get the one you just did but another.
Anyhow, an alternative to other methods.

C# SqlParameter - provide SQL (Microsoft SQL)

I am currently tasked with a project on a database whose schema cannot be changed. I need to insert a new row into a table that requires an ID to be unique, but the original creators of the structure did not set this value to autoincrement. To go around this, I have been using code akin to:
(SELECT TOP 1 [ID] from [Table] ORDER BY [ID] DESC) + 1
when giving the value of the ID field, basically having an inner query of sorts. Problem is that a few lines down, I need that ID I just inputted. If I could set a SQLParameter to output for this column, I could get the value it was set to, problem is I'm using SQL, and not a hard value like I do with other SQLParameters. Can't I use SQL in place of just a value?
This is a potential high volume exchange, so I'd rather not do 2 different queries (one to get id, then one to insert).
You say you cannot change the schema, but can you add an additional table to the project that does an autoincrement column? Then you could use that table to (safely) create your new IDs and return them to your code.
This is similar to how Oracle does IDs, and sometimes vendor applications for sql server that also run on Oracle will use that approach just to help minimize the differences between the two databases.
Update:
Ah, I just spotted your comment to the other answer here. In that case, the only other thing I can think that might work is to put your two statements (insert a new ID, and then read back the new ID) inside a transaction with the SERIALIZABLE isolation level. And that just kinda sucks, because it leaves you open to performance and locking gotchas.
Is it possible for you to create a stored procedure in the database to do this and the return value of the stored procedure will then return the ID that you need?
I'm a bit confused about where you need to use this ID. If it inside of the same stored proc just use this method:
DECLARE #NewId int
SELECT TOP 1 #NewId = [ID] + 1 from [Table] ORDER BY [ID] DESC
SELECT #NewId
You can put more than one SQL statement in a single SqlCommand. So you could easily do something along the lines of what Abe suggested:
DECLARE #NewId int
SELECT TOP 1 #NewId = [ID] + 1 from [Table] ORDER BY [ID] DESC
INSERT INTO [Table] (ID, ...) VALUES (#NewId, ...)
SELECT #NewId
Then you just call ExecuteScalar on your SqlCommand, and it will do the INSERT and then return the ID it used.

Can I create a table with check constrain whose values are dependent on sql query

Is it possible to create a table which has a check constraint on one of the column whose value lies within the result set given by another sql query
eg.
create table tablename
(
name varchar(10),
rollno int
)check rollno in (select rollno from anotherDatabase.TableName,candidateRoll)
or any thing like that.
I dont have to use it anywhere but still want to know.
If you can't achieve what you want with a foreign key reference, so you can if you wrap the SELECT statement in a function call.
Your check constraint expression may look something like:
(dbo.SomeFunction([col1]) != 0)
The function might look like this (assuming the column is a varchar):
create function dbo.SomeFunction(#arg varchar(max))
returns bit
as
begin
return
(
select count(*) from SomeOthertable where col2 = #arg
)
end
EDIT (2010/06/9): Regarding Anthony's comment, my testing has shown that a count(*) value of greater than 1 is still returned as 1. So it would seem that the function is okay, even though it should probably explicitly return 1 or 0. Or, if you are interested in the actual rowcount, change the return type from BIT to INT.
Yes: foreign key for same database links
create table tablename
(
name varchar(10),
rollno int FOREIGN KEY (candidateRoll) REFERENCES OtherTableName (candidateRoll)
)
If it's a different database then use code e.g. insert via stored proc or enforce via a trigger

Share auto-incremented primary key between two tables

Hi I want to have two tables each have an INT "id" column which will auto-increment but I don't want either "id" columns to ever share the same number. What is this called and what's the best way to do it? Sequence? Iterator? Index? Incrementor?
Motivation: we're migrating from one schema to a another and have a web-page that reads both tables and shows the (int) ID, but I can't have the same ID used for both tables.
I'm using SQL Server 9.0.3068.
Thanks!
Just configure the identity increment to be >1 e.g. table one uses IDENTITY (1, 10) [1,11,21...] and table two uses IDENTITY (2, 10) [2,12,22...]. This will also give you some room for expansion if needed later.
I think using a GUID would be the most straightforward way, if I understand you correctly.
SELECT NEWID()
Use a column with GUID (Globally Unique Identifier) type. It's 16 byte and will be always unique for each row.
Just be aware that you'll get a significant performance hit comparing to normal integer keys.
Use another table with an ID key of type int default it to 1, called KeyID or whatever.
Have a stored procedure retrieve the value, add 1, then update the KeyID, then return this to the stored procedure which is updating your two tables which needs the new unique key.
This will ensure the ID is an int, and that it's unique between the set of tables which are using the stored procedure to generate new ID's.
You can define an IDENTITY column in a third table, use that to generate ID values, but you always roll back any inserts you make into the table (to avoid making it grow). Rolling back the transaction doesn't roll back the fact that the ID was generated.
I'm not a regular user of Microsoft SQL Server, so please forgive any syntax gaffes. But something like the following is what I have in mind:
CREATE TABLE AlwaysRollback (
id IDENTITY(1,1)
);
BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;
INSERT INTO RealTable1 (id, ...) VALUES (SCOPE_IDENTITY(), ...);
BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;
INSERT INTO RealTable2 (id, ...) VALUES (SCOPE_IDENTITY(), ...);
I don't know what you would call it.
If you don't want to use a GUID or a separate table, you could also create a function that looked at the max values of the ids from both tables and added one to the that value (or something like that).
You could then call that function in an insert trigger on both tables.
I am personally a fan of the GUID solution, but here is a viable option.
Many solutions to this problem have avoided GUID and used good old integer. This is common also with merge replication situations where many satellite sites merge with a master and key conflicts need to be avoided.
If GUID will not work for you, and you absolutely must have int, bigint, or the like, you can always just use an IDENTITY column and have each table with a different value for SEED. Those datatypes have a very wide range, and it is not too hard to split the range into usable segments, especially if all you want is two splits. As an example, basic int has a range from -2^31 (-2,147,483,648) through 2^31 - 1 (2,147,483,647). This is more than enough for a customer table, for example.
Transact-SQL Reference (SQL Server 2000)
int, bigint, smallint, and tinyint
Example:
--Create table with a seed of 1 billion and an increment of 1
CREATE TABLE myTable
(
primaryKey int IDENTITY (1000000000, 1),
columnOne varchar(10) NOT NULL
)
If you really need to do this with an int and you have an auto incrementing number, the way i have done this before is to change the id field auto increment function to the sequence of the other table. I am not too sure in ms sql or my sql but in pgsql that means that in the sql you would have this field
id integer NOT NULL DEFAULT nextval('table_two_seq'::regclass),
where table_two_sequence is the sequence function for the other table. Then test it out by inserting some data. I am really sorry if this wont work in ms sql i try to steer clear of it tbh. Failing that the GUID is the best way as has been mentioned by others. Or when inserting in the code that you use you could put an algorithm in that but it could get messy.
Alternatively, think about having the data in one table as this would be a way around it. if you need to you could have a view simulating two tables. Just a thought.
Hope i have helped
Starting with SQL Server 2012 you can declare a sequence object
https://msdn.microsoft.com/en-us/library/ff878091.aspx which is exactly what you need.
I should be pretty trivial to emulate a sequence object with a table
containing the next sequence value and a stored procedure atomically
select the value and increment. [You'd liked to use function, but functions
can't have side effects.]
How about this hack? Create a table (MySequence) with two columns: And Identity column (SequenceValue) and a dummy column (DummyValue) and use this stored procedure to get a new sequence value. The only row in the table will be last sequence value retrieved.
CREATE PROCEDURE GetNextValue
AS
BEGIN
DECLARE #value int = null;
-- Insert statements for procedure here
INSERT into MySequence (DummyValue) Values (null);
SET #value = SCOPE_IDENTITY();
DELETE from MySequence where SequenceValue <> #value
SELECT #value as Sequence
return #value
END
To use the sequence you'd have to manage the inserts to the target tables--a trigger would probably work.