PUT is not UPDATE

PUT remains one of the most confusing HTTP verbs because it is so frequently misdescribed, even by people who really do know better. The common description is that PUT is for UPDATE and POST is for creating new resources; and this is wrong, wrong, wrong.

UPDATE, in the SQL sense, means we change some fields to some values; e.g.

UPDATE customers
SET sucker = true
WHERE bought_extended_service_warranty = true

This is not HTTP PUT at all. HTTP has no notion of a diff or a partial update. The only thing you can do in HTTP is send the entire resource again, to completely replace the existing resource. There’s really no equivalent in SQL, but if you must have one, then PUT is like a DELETE, followed by an INSERT, using the same primary key.

Of course, PUT can also be used to create new resources that did not exist before with new primary keys (URLs). This is sort of like an INSERT with a client supplied primary key.

In fact, POST is better suited to serve as an UPDATE clone if you need one. If you’re updating a page, you can POST a diff or comment to it, and the server can respond by applying those changes to that page. This requires a more intelligent server than most of us have bothered to install. This is also not the only thing that POST can do, but it is well within POST’s allowed behavior. If you really want to duplicate SQL UPDATE in HTTP, you do it with POST, not with PUT.

Bottom line: PUT is for creating and replacing pages. It updates only in so far as replacing an entire page is an extreme case of updating it. POST is the real UPDATE if anything is. Of course, the ultimate reality is that the SQL analogy is strained to the breaking point by both PUT and POST. HTTP is not SQL, and those who persist in thinking of it like that will continue to be confused.

31 Responses to “PUT is not UPDATE”

  1. Alan Dean Says:

    You are correct.

    Unfortunately, I think that the APP is misleading on this:

    http://bitworking.org/projects/atom/draft-ietf-atompub-protocol-14.html#model

  2. Elias Torres Says:

    … and there’s always PATCH. But like you said it requires intelligent servers that are not usually installed and very few have even bothered to implement. However, as APP reaches wide deployment there will be many looking into PATCH for quick updates like: change the title, fix this typo, etc.

  3. The Cafes » PUT is not UPDATE at 16cards Says:

    […] Source: PUT is not UPDATE […]

  4. Julian Reschke Says:

    Actually, UPDATE would be the HTTP method PATCH (http://tools.ietf.org/html/rfc2068#section-19.6.1.1).

    Best regards, Julian

  5. Patrick Mueller Says:

    PUT is also not “UPDATE” in the sense that update means “modernize”. But you bring up a good point. Has everyone become so brainwashed by SQL that the term UPDATE has some implied meaning that we all need to take into account when we use it? Yikes! A member of the few, the proud, the folks who avoid databases at all costs.

  6. Elias Torres Says:

    hmm… 3 first posts made by IBMers, is this what IBMers do on a lovely sunny Saturday morning?

  7. robert Says:

    avoiding databases is like avoiding surgery for voodoo. the web is a 1960s block mode interface to files, if left to its own devices. people (some anyway) have gotten smarter than that since then. yunguns who don’t know what progress had been made blissfully ignore it. the relational database (and even the SQL ones that do exist) are a result of intelligent design. those who ignore history are doomed to repeat it.

  8. Donavon Keithley Says:

    There are other alternatives to DBMSes besides flat file storage, like object prevalence (http://en.wikipedia.org/wiki/Object_Prevalence). A web app using object prevalence can run dizzying circles around one backed by a SQL DB, while also being much simpler and cheaper to implement.

  9. David Smith Says:

    Hmmm… as long as your title “PUT is not UPDATE” is short for “(HTTP) PUT is not (SQL) UPDATE”, it makes sense. Or am I the only person left who doesn’t take it for granted that every web service fronts for a SQL database?

  10. Stefan Tilkov Says:

    I agree that the connection to SQL UPDATE is misleading. In abstract terms, PUT is much more like ‘update’ than POST, for a simple reason: I use PUT when I know the URI of the resource being affected (updated/replaced), and POST when I expect a new URI to be returned (or some arbitrary processing to occur).

  11. assaf Says:

    SQL does indeed have an UPDATE statement that is nothing like PUT. It also has a SELECT that is no match for GET, and an INSERT that can create multiple entities at once.

    HTTP is not SQL and SQL is not HTTP.

    But I think most people refer to the UPDATE in CRUD. Which is conceptual, and not a particular dialect of SQL. It’s a general classification long used outside the strict world of relational databases. And in that CRUD classification, PUT falls under UPDATE.

  12. Hans Ridder Says:

    I think you bring up some interesting points on the meaning and uses of PUT and POST, however I think it’s a mistake to assume that “we all” mean SQL UPDATE when we offhandedly say “PUT means update.” I personally don’t think of HTTP as an interface to an SQL database. Perhaps in your circles some people do, and that’s a source of confusion. I particularly liked your observation that PUT and POST can be interpreted almost exactly opposite from the common wisdom.

    PUT certainly does mean update in the sense that it can replace an exisiting resource at the specified URI. But yes, it can also create resources. See the RFC. Whether it can be used for each of these depends on the application (of the protocol.)

    I’m pleased people are at least talking about how to use HTTP properly, even if we get it wrong sometimes. Just think how much further we’d be down this road if we spent as much time on it as has been spent on WS-* and SOAP.

  13. Danny Says:

    Ok, I think it’s been established that (HTTP) PUT is different than (SQL) UPDATE. One place this discussion may actually have practical value is around SPARQL – a query language that looks and behaves very much like SQL, but is intended (at least potentially) to be usable directly over the web.

    The current SPARQL spec only covers GET-like operations, and the mapping of e.g. SELECT queries to GET methods is fine (basically it’s done as http://example.org/x?query=%5BURL-encoded query], hence the whole URI is the resource with a representation containing the query results).

    But the mismatch between the SQL style of SPARQL and HTTP starts getting a bit uncomfortable when UPDATE operations are brought in. Andy Seaborne’s just published a proposed spec for SPARQL/Update, it could do with more eyeballs…

    Relevant links at : http://dannyayers.com/2007/03/09/sparql-update

  14. Gerard Tixier Says:

    my 2 cents:
    the INSERT/UPDATE dilemma can be addressed by resorting to headers If-Match and If-None-Match
    the following is an Insert:
    PUT ….
    If-None-Match: *

    the following is an Update:
    PUT ….
    If-Match: *

    BR, Gerard.

  15. Keith Gaughan Says:

    In fact, if there’s any SQL equivalent of PUT, it’s got to be MySQL’s proprietory REPLACE statement.

  16. Jeff Says:

    RTFA.

    I hesitated to include this table. By presenting it, I wanted to point out the overlap in the four basic methods of HTTP. What I don’t want to happen is that you start thinking of web resources as SQL tables. Don’t do that.

  17. ocean Says:

    I don’t think this is true. The payload of a PUT request is a representation of the resource. The server is then allowed to interpret this representation in any way it wants as long it respects the logical ‘replace that with this’ constraint on PUT. So it’d be perfectly fine to submit a ‘partial’ representation in a PUT it just might not be 100% kosher.

  18. Mike Schinkel Says:

    Rusty: You are right that (HTTP) PUT isn’t (SQL) UPDATE, but not in the way you are suggesting. PUT isn’t UPDATE because PUT is a subset of UPDATE as HTTP doesn’t have the functionality that UPDATE has. UPDATE can update multiple end points, PUT can only update one. Using SQL sytntax to put a new delivery date to invoice #12345 at api.example.com (NOTE there is no need for a WHERE clause):

    UPDATE api.example.com
    SET [/invoices/12345/delivery-date/] = ‘2007-03-15’

    What HTTP can’t do is update more than one ‘record’ (resource) which is why the WHERE clause is not needed.

    Of course you could argue that HTTP PUT has more power than SQL UPDATE because most SQL implementations cannot do this. Here’s my TSQL psuedo-code showing the ability to declare an “invoice resource”:

    DECLARE @Inv12345 AS ‘invoice-resource’
    EXEC prc_GetInvoice @InvoiceNo= 12345, @invoice= @Inv12345 OUT
    UPDATE api.example.com
    SET [/invoices/12345/] = @Inv12345

    However, with the ability to store JSON in TEXT fields or XML is XML fields, SQL *can* do that (well, you can’t index into JSON and update portions of a JSON resource using SQL like you can on many servers with XML and XPATH.)

  19. Bert Lamb » links for 2007-03-13 Says:

    […] The Cafes » PUT is not UPDATE (tags: rest WebServices) […]

  20. Tom Says:

    As Hans stated, the biggest point of confusion here is trying to draw a direct correlation between HTTP methods and a RDBMS. It’s naive to always map a single URI to a single entity an a database. You could have a resource in a URI that is made up of several tables in the database, as the concepts in your application may exceed the concepts of your database (think DDD).

    Partial updates are also important for high transactional web apps. Often times you only want to update select columns in a table, as some may rarely if ever change, or changing them could cause index updates and other side effects that could be avoided. I’ve worked on enough projects where always trying to update everything can cause contention and other nasties in the database.

    HTTP methods should be used in the context of the resources they’re being applied to, as the RFC is not a panacea

  21. Mike Says:

    Yes, HTTP’s PUT is not SQL’s UPDATE. But, it certainly is CRUD’s UPDATE. Read it here (pages 54 and 55): HTTP 1.1: http://www.ietf.org/rfc/rfc2616.txt

  22. Kevin Marks Says:

    The only thing you can do in HTTP is send the entire resource again, to completely replace the existing resource. There’s really no equivalent in SQL, but if you must have one, then PUT is like a DELETE, followed by an INSERT, using the same primary key.

    There is an equivalent in MySQL called REPLACE, which does exactly that (and is not recommended because of the index churn it causes).

  23. Adam Taft Says:

    Elias Torres Says:
    … and there’s always PATCH.

    No there’s not. You’re reading a DRAFT of the HTTP/1.1 spec. The FINAL spec does not include PATCH or many of the other (arguably useful) methods in it (like COPY, MOVE, etc. though these are in Webdav to a certain extent).

    http://www.w3.org/Protocols/rfc2616/rfc2616.html

  24. Peter Keane Says:

    While we are throwing SQL analogies around, one that I have found quite useful is to think of POST as ‘get next insert id’ (Postgres users may appreciate the need for this — MySQL users are generally content w/ auto-increment ids and don’t need to think about things like sequence generators).

    To add a new resource, I ‘POST’ to the collection url and get back a unique identifier. I can use it then and there to ‘PUT’ a resource OR I can forget about it — the server agrees to never hand out that same ID again — whether it actually creates the ’empty’ resource a that ID or not can be an implementation detail (it may be useful to have a return code other than 404 in response to a GET on that id — something that says ‘no resource at this ID, but it has already been claimed’). So implementing POST on the server is pretty simple….

    Any thoughts on that?

  25. Paul Downey » Blog Archive » A New Resource, Please Says:

    […] Other people disagree, but the most convincing comments against my preference come from an optimistic Paul. […]

  26. Meble Says:

    I’m pleased people are at least talking about how to use HTTP properly, even if we get it wrong sometimes. Just think how much further we’d be down this road if we spent as much time on it as has been spent on WS-* and SOAP.

  27. Licea Krakowskie Says:

    Great!!! Often times you only want to update select columns in a table, as some may rarely if ever change.

  28. kominki Says:

    I in addition to my friends have been looking through the good secrets located on the website then all of a sudden got an awful feeling I never thanked you for those strategies. All of the men are already totally happy to study all of them and already have sincerely been using these things. Appreciate your indeed being well helpful and for opting for variety of decent issues most people are really wanting to be aware of. My personal honest regret for not expressing appreciation to you earlier.

  29. Dave Says:

    Frankly, I think that using POST to apply changes to a resource is just as much an abuse of the HTTP spec as using PUT to do the same thing. PATCH is really how that should be done.

  30. andrewbecks Says:

    I know that this post is from 2007, but I just wanted to say how helpful I found this explanation. I think you really hit the point home with your bottom line, but for me, I find it’s often nice to use these sort of apologies to help explain new concepts to students and people just getting started in MySQL but who have a foundational knowledge of HTTP, and vice versa. Plus, when you layer in the caveats, it starts to help people really understand the fundamental differences between the HTTP application protocol and relational database model interaction.

  31. Services RESTful et opérations de mise à jour Says:

    […] N'est pas mise à JOUR […]