How can I restore removed menu items? I create a menu "XXXX" move "Create content" and all of it's children to "XXXX" then remove XXXX menu. now I miss "Create content", how can I restore them?
You can execute the following query.

if ($mlid = db_query("SELECT mlid from {menu_links} WHERE link_path = :path AND menu_name NOT LIKE :menu", array(':path' =&gt; 'node/add', ':menu' =&gt; db_like('shortcut-set-') . '%'))-&gt;fetchField()) {
  db_update('menu_links')
    -&gt;fields(array('menu_name' =&gt; 'navigation', 'plid' =&gt; 0))
    -&gt;condition('mlid', $mlid)
    -&gt;execute();
  db_update('menu_links')
    -&gt;fields(array('menu_name' =&gt; 'navigation', 'plid' =&gt; $mlid))
    -&gt;condition('link_path', db_like('node/add/') . '%', 'LIKE')
    -&gt;condition('menu_name', db_like('shortcut-set-') . '%', 'NOT LIKE')
    -&gt;execute();
}
else {
  // There isn't any row for node/add.
}


What the code does is the following.


It finds the database row where the link path is node/add, and where the menu name doesn't start with shortcut-set-, which is the menu name used from the Shortcut module for its shortcut sets; as the default shortcut set used from that module contains a link that points to node/add, the code exclude that link. If there are other rows that would point to node/add, you need to edit the first query to exclude them.
For the row found from the first query, it changes the menu name to navigation, and plid (the parent link ID) to 0.
For any row whose link path matches the SQL regular expression node/add/%, it sets plid to the mlid previously found.


In the code I used db_like(), even in this case was not strictly necessary. The purpose of db_like() is escaping any character that for the SQL regular expressions has a specific meaning. Suppose that I would change the code to find any database row whose link path is node/%, where % is the character that is really present in the link path; without db_like(), the query would find any row where the link path starts with node/, which would include more rows than the ones where the link path is node/%.

As the code is using two update queries, it should use transactions. In that way, if the second query would fail, the database would be left in a consistent state, which means that the rows for node/add, and node/add/[content type] will be part of the same menu. If the first query is executed, and the second one fails, you would have node/add that is part of a menu, while any node/add/[content type] link would be part of a different menu (or some of the node/add/[content type] links will be part of a menu, and other node/add/[content type] links will part of another menu).

if ($mlid = db_query("SELECT mlid from {menu_links} WHERE link_path = :path AND menu_name NOT LIKE :menu", array(':path' =&gt; 'node/add', ':menu' =&gt; db_like('shortcut-set-') . '%'))-&gt;fetchField()) {
  $transaction = db_transaction();
  try {
    db_update('menu_links')
      -&gt;fields(array('menu_name' =&gt; 'navigation', 'plid' =&gt; 0))
      -&gt;condition('mlid', $mlid)
      -&gt;execute();
    db_update('menu_links')
      -&gt;fields(array('menu_name' =&gt; 'navigation', 'plid' =&gt; $mlid))
      -&gt;condition('link_path', db_like('node/add/') . '%', 'LIKE')
      -&gt;condition('menu_name', db_like('shortcut-set-') . '%', 'NOT LIKE')
      -&gt;execute();
  }
  catch(Exception $e) {
    // One of the queries failed; rollback the database to the previous status.
    $transaction-&gt;rollback();
  }
}
else {
  // There isn't any row for node/add.
}


PS: As the only way to find the menu item is too look for its link path, there could be more than one row using that link path. It is important the code excludes those rows that are not the correct one, and that is what my code does when it excludes the rows there the menu name starts with shortcut-set-. Unfortunately, it is not possible to write code that generic enough to work in any condition.