Using OUTPUT for SQL Server 2008 on update? - sql-server-2008

I am using SQL Server 2008 with GUIDs in all my tables and using some stored procedures. I want to know if there is a way to output the current GUID that you are updating to?
I know there is the codes below that I use in other procedures:
output inserted.*
output deleted.*
However, I have a case that is an if null insert, else, update. I would like to know which GUID was used in each case. I have heard another way where you create another table, set the value in the table to that the just updated GUID and then SELECT the value from the newly created table, but that just seems extremely redundant and unnecessary. Any workarounds?
Thanks!

Do you have newid() as the default for the column or are you generating a guid in your code when you do insert/update?
If you have a default on it of NewID() then there isn't a way to grab the last inserted/updated one, had it been identity you could have used ##IDENTITY to get the last inserted ID.
Only way I can think of to do what you want is to take the default off the column, generate a NewID() in your code for insert and remember what that was.
(This answer was made with the assumption you're using GUIDS as PK's)

Related

How to convert mssql user-defined table type into mysql UDT

This is my mssql UDT
create type ConditionUDT as Table
(
Name varchar(150),
PackageId int
);
This is my mssql Stored Procedure
create Procedure [dbo].[Condition_insert]
#terms_conditions ConditionUDT readonly
as
begin
insert into dbo.condition (name, p_id)
select [Name],[PackageId]
from #terms_conditions;
end
There is a workaround solution if you do not have any other choice but definitely migrate from sql server to mysql.
The closest structural predefined object that takes on many rows in mysql is an actual table. So you need 1 table per UDDT of sql server. Make sure you use a specific schema or naming conversion so you know those tables are UDDT emulations.
The idea is fill in the info, use them into the sp and then delete them. You need however to gurantee who reads what and that info are deleted after usage, consumed. So:
For any of those tables you need 2 columns, i suggest put them always first. That will be the key and the variable name. The key can be char(38) and use UUID() to get a unique identifier. It can also be int and use the connectionid() instead. Unique identifier is better however as ensures that nobody will ever use information not indented for him no matter what. The variable name will be the one used into the sql server parameter, just a string. This way:
You know what UDDT you use out of the table name.
You know the identity of your process through the key.
You know the 'variable' out of the name.
So, in your application code you:
Begin transaction.
Insert the data into the proper (UDDT emulator) tables using a key and the variable name(s)
Supply to the stored procedure the key and the variable name(s). You can use the same key for many table type parameters within the same sp call.
The stored procedure can now use that information as before from the UDDT variable using key and variable name as filters to query the proper UDDT emulated table.
Delete the data you insert
Commit
On catch, rollback.
For simplicity your sp can read the data into temp table and you do not need to change a line of code from the original sql server sp for this aspect.
Transaction into your app code will help you make sure your temporary variable data will either be deleted or never committed no matter what goes wrong.
As Larnu thought might be the case, MySQL doesn't support user defined types at all, let alone user defined table types.
You will have to make them all separate scalar parameters.

MySQL MD5(CURRENT_TIMESTAMP) On Update

I'm creating a user registration form and when I get to confirming the user's email by emailing them, I need some sort of unique string to confirm against.
Instead of generating one in PHP and inserting it into the database, I wanted to try and add a column to my table that would hold a unique value that I could use whenever I needed to confirm something.
What I want to do is set the value to an MD5 of the current timestamp. I tried just doing SELECT MD5(CURRENT_TIMESTAMP) in phpMyAdmin just to see if it would let me and it did so I thought I'd add that to an update condition but it doesn't seem to be letting me.
ALTER TABLE users ADD confirmation VARCHAR(40) DEFAULT NULL ON UPDATE MD5(CURRENT_TIMESTAMP);
The above is what I've tried. I get an error and I don't know how else to do it.
Is there anyway I can do this or something similar? Side question, does the ON UPDATE trigger on a row that just got inserted?
The syntax you are trying to use doesn't exist. It looks like you are thinking of ON UPDATE CURRENT_TIMESTAMP but that is a rather specific command, as per https://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
Use of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP is
specific to TIMESTAMP.
So the ON UPDATE clause only works with CURRENT_TIMESTAMP and only on fields of type TIMESTAMP.
If you want to use the MD5 of the current timestamp either set a trigger, or just manually set the value (e.g. UPDATE users SET confirmation=MD5(CURRENT_TIMESTAMP()) WHERE user_id=123).
Bare in mind that the MD5 of the current timestamp is something that could be quite easily guessed / brute forced, so don't rely on it for security.
Use a universal unique identifier for this purpose. It's a 128-bit unique number; it's designed for this kind of thing.
It has a string representation that fits in 36 bytes.
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
You can generate these things in most programming languages. In MySQL you use the UUID() function to get one. Every time you call UUID(), you're guaranteed to get a new value.
Add a CHAR(36) column to your database, or just use your VARCHAR(40) column.
You can't use data definition language (ALTER TABLE) to declare ON UPDATE except for a native timestamp. You'll need application code to set your UUID values, just like you do for MD5(CURRENT_TIMESTAMP).

MySQL and implementing something close to sequences?

I am recently in the process of moving from oracle to mysql and would like some advice if how i am implementing something similar to sequences in mysql is a good way.
Essentially how i am currently going to implement it is by having a separate table in mysql for each sequence in oracle and have a single column which represents the last_number and increment this column when ever i insert a new row, that's one way another way i could go about doing it is by creating a single table with several rows representing each sequence and increment each row separately whenever i do an insert.
Another simpler way of doing it i could just do a select max()+1 on the relevant column when inserting data.
I'm basically thinking of switching to the select max()+1 option as it seems simpler to implement, but i would like to get some advice on what you think would be the best way of doing it out of these options, and if there is any pitfalls that i am currently not aware of when using select max()+1.
Also the reason im am not using auto_increment and the function last_insert_id() is i want to follow the ansi standard.
Thanks.
First of all: The max()+1 version is NOT guaranteed to give you a sequence, if you use transactions in a high isolation level.
The way we typically use sequences (if we can't avoid them) is to create a table with an AUTO_INCREMENT value, INSERT INTO it, SELECT last_insert_id(), DELETE FROM table WHERE field<$LASTINSERTID. This is ofcourse done in a stored procedure.
There is a read consistency problem, in that two sessions both running ...
insert into ... select max(..)+1 from ...
... at the same time both see the same value of max(...), hence they both try to insert the same new value.
You have the same problem with your table of maxima method, and you have to use a locking mechanism to avoid multiple session reading the same value. This leads to a concurrency problem where inserts to the table are serialised.

Can I INSERT/UPDATE into two tables with one query?

Here is a chunk of the SQL I'm using for a Perl-based web application. I have a number of requests and each has a number of accessions, and each has a status. This chunk of code is there to update the table for every accession_analysis that shares all these fields for each accession in a request.
UPDATE accession_analysis
SET analysis_id = ? ,
reference_id = ? ,
status = ? ,
extra_parameters = ?
WHERE analysis_id = ?
AND reference_id = ?
AND status = ?
AND extra_parameters = ?
and accession_id is (
SELECT accesion_id
FROM accessions
where request_id = ?
)
I have changed the tables so that there's a status table for accession_analysis, so when I update, I update both accession_analysis and accession_analysis_status, which has status, status_text and the id of the accession_analysis, which is a not null auto_increment variable.
I have no strong idea about how to modify this code to allow this. My first pass grabbed all the accessions and looped through them, then filtered for all the fields, then updated. I didn't like that because I had many connections with short SQL commands, which I understood to be bad, but I can't help but think the only way to really do this is to go back to the loop in Perl holding two simpler SQL statements.
Is there a way to do this in SQL that, with my relative SQL inexperience, I'm just not seeing?
The answer depends on which DBMS you're using. The easiest way is to create a trigger on one table that provides the logic of updating the other table. (For any DB newbies -- a trigger is procedural code attached to a table at the DBMS (not application) layer that runs in response to an insert, update or delete on the table.). A similar, slightly less desirable method is to put the logic in a stored procedure and execute that instead of the update statement you're now using.
If the DBMS you're using doesn't support either of these mechanisms, then there isn't a good way to do what you're after while guaranteeing transactional integrity. However if the problem you're solving can tolerate a timing difference in the two tables' updates (i.e. The data in one of the tables is only used at predetermined times, like reporting or some type of batched operation) you could write to one table (live) and create a separate process that runs when needed (later) to update the second table using data from the first table. The correctness of allowing data to be updated at different times becomes a large and immovable design assumption, however.
If this is mostly about connection speed, then one option you have is to write a stored procedure that handles the "double update or insert" transparently. See the manual for stored procedures:
http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html
Otherwise, You probably cannot do it in one statement, see the MySQL INSERT syntax:
http://dev.mysql.com/doc/refman/5.5/en/insert.html
The UPDATE syntax allows for multi-table updates (not in combination with INSERT, though):
http://dev.mysql.com/doc/refman/5.5/en/update.html
Each table needs its own INSERT / UPDATE in the query.
In fact, even if you create a view by JOINing multiple tables, when you INSERT into the view, you can only INSERT with fields belonging to one of the tables at a time.
The modifications made by the INSERT statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For example, an INSERT into a multitable view must use a column_list that references only columns from one base table. For more information about updatable views, see CREATE VIEW.
Inserting data into multiple tables through an sql view (MySQL)
INSERT (SQL Server)
Same is true of UPDATE
The modifications made by the UPDATE statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For more information on updatable views, see CREATE VIEW.
However, you can have multiple INSERTs or UPDATEs per query or stored procedure.

Overwriting data in a MySQL table

With the query below, I am trying to overwrite the 10th field in a MySQL table called "login" with the value NEW_VALUE. It's not working. Is the code below the correct method for overwriting existing data in a MySQL table?
Thanks in advance,
John
INSERT INTO login VALUES (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'NEW_VALUE', NULL, NULL, NULL)
Just as an addition if anyone is still looking for an actual overwrite and not just an update. If you want to OVERWRITE always, (not update, just overwrite) you can use REPLACE instead of INSERT.
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, “INSERT Syntax”
http://dev.mysql.com/doc/refman/5.5/en/replace.html
No your code is not correct. You are adding a new row to your table not updating existing values. To update existing values, you want to use an update statement:
Upate a specific record
mysql_query("Update login SET nameOfYourColumn = '$cleanURL' WHERE primaryKey = idOfRowToUpdate")
To update the entire table
mysql_query("Update login SET nameOfYourColumn = '$cleanURL'")
If I've understood your question then the answer is "no". This isn't a mysql specific issue either, it's a generic SQL question. I'd strongly recommend going through an SQL tutorial, the best one I know if is here:
http://philip.greenspun.com/sql/
To answer your question, you should be able to do:
mysql_query("UPDATE login SET foo = '$cleanurl'");
where "foo" is the name of the tenth field.
A few other comments though:
Firstly, don't rely on the position of your fields, always explicitly list the field names. For example, it's better to go
INSERT INTO login (id, name) VALUES (1, 'Fred')
instead of
INSERT INTO login VALUES (1, 'Fred')
Point 2: You have directly embedded the value of $cleanurl into your query. Of course, you have to learn one thing at a time but be aware that this is very dangerous. If $cleanurl contains something like "'); DROP TABLE login;" then you might be in trouble. This is called SQL injection and is the source of constant security problems. Without going into too much detail, you should learn how to use prepared statements.
Point 3: PHP comes with a library called PDO which supports prepared statements. It also provides a common API for interacting with your database so if you find that you need to move from Mysql to another DBMS, PDO will abstract away most of the differences. By using the mysql_query function you lock yourself into using mysql.
You don't have to address all of these issues simultaneously but don't forget about them either, once you get familiar with PHP and SQL come back to the points about PDO and prepared statements.
First off: INSERT adds a new record to a table, UPDATE updates (overwrites) one or more existing records.
Second: UPDATE needs to know the name of the column to update, and which rows to update
UPDATE <tableName>
SET <columnName> = '$cleanurl'
WHERE <some condition to identify which record should be updated>
Thirdly: it's probably worth your while reading a few basic tutorials on MySQL/SQL