diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 01d806ef3b90b375f11903630ccc32e3a61c02eb..4709a64daf23b5628ae69bfd8f4877cb37abbe74 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -69,7 +69,7 @@ unittests-mysql-8:
   # Should not stop the pipeline from continuing.
   allow_failure: true
   services:
-    - name: mysql:8.0
+    - name: mysql:8.0.32
       command: ["--default-authentication-plugin=mysql_native_password"]
 
   script:
@@ -84,7 +84,7 @@ unittests-mysql-5:
   # Should not stop the pipeline from continuing.
   allow_failure: true
   services:
-    - name: mysql:5.7
+    - name: mysql:5.7.36
       command: ["--default-authentication-plugin=mysql_native_password"]
 
   script:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e41b4611e97316a25933db6ecaf0c51b79f00be..d674221f0d4de2c6584d2ca68335b1caa9d1d39d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,16 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased] ##
 
+This is a major update. Switching from integer ids for internal and external use to string ids for the external use while keeping the old integer ids for internal use.
+
 ### Added ###
 
+* Table `entity_ids`
+* Procedure `getIdByName`
+* Procedure `insertEntityDataType` and `insertEntityCollection`
+* Procedure `setFileProperties`.
+
 ### Changed ###
 
+* Rename PROCEDURE `registerSubdomain` to `registerReplacementIds`.
+* Change column `entities.role` datatype: replace 'DOMAIN' enum value with `_REPLACEMENT`.
+* Change column `transactions_log.entity_id` to VARCHAR(255)
+* Change column `user_info.entity` to VARCHAR(255)
+* Change signature of procedure `applyIDFilter` - `EntityID VARCHAR(255)`
+* Change signature of procedure `initBackreference` - `EntityID VARCHAR(255)` and `PropertyID VARCHAR(255)`
+* Change signature of procedure `initPOVPropertiesTable` - `PropertyID VARCHAR(255)`
+* Change signature of procedure `initPOVRefidsTable` - `PropertyID VARCHAR(255)`
+* Change signature of procedure `initSubEntity` - `EntityID VARCHAR(255)`
+* Change signature of procedure `deleteEntity` - `EntityID VARCHAR(255)`
+* Change signature of procedure `deleteEntityProperties` - `EntityID VARCHAR(255)`
+* Change signature of procedure `get_primary_parent_version` - `EntityID VARCHAR(255)`
+* Change signature of procedure `get_version_timestamp` - `EntityID VARCHAR(255)`
+* Change signature of procedure `get_head_version` - `EntityID VARCHAR(255)`
+* Change signature of procedure `get_head_relative` - `EntityID VARCHAR(255)`
+* Change signature of procedure `get_version_history` - `EntityID VARCHAR(255)`
+* Change signature of procedure `retrieveQueryTemplateDef` - `EntityID VARCHAR(255)`
+* Change signature of procedure `getDependentEntities` - `EntityID VARCHAR(255)`
+* Change signature of procedure `insertEntity` - Add parameter `EntityID VARCHAR(255)`
+* Change signature of procedure `insertEntityProperty` - `EntityID VARCHAR(255)` and `PropertyID VARCHAR(255)`, `DomainID VARCHAR(255)`, `DatatypeOverride VARCHAR(255)`
+* Change signature of procedure `insertIsa` - `ChildID VARCHAR(255)`, `ParentID VARCHAR(255)`.
+* Change signature of procedure `isSubtype` - `ChildID VARCHAR(255)`, `ParentID VARCHAR(255)`.
+* Change signature of procedure `retrieveEntity` - `EntityID VARCHAR(255)`
+* Change signature of procedure `retrieveOverrides` - `EntityID VARCHAR(255)`, `DomainID VARCHAR(255)`
+* Change signature of procedure `retrieveEntityParents` - `EntityID VARCHAR(255)`
+* Change signature of procedure `retrieveEntityProperties` - `EntityID VARCHAR(255)`, `DomainID VARCHAR(255)`
+* Change signature of procedure `updateEntity` - `EntityID VARCHAR(255)`
+
 ### Deprecated ###
 
 ### Removed ###
 
+* Deactivate procedure `delete_all_entity_versions`. This might be used in the
+  future, that is why we keep the code in a comment.
+* Drop procedure `retrieveSubEntity`
+* Drop procedure `retrieveDatatype`
+* Drop procedure `retrieveGroup`
+* Drop procedure `getInfo`
+* Drop procedure `getRole`
+* Drop procedure `setPassword`
+* Drop procedure `initAutoIncrement`
+* Delete special entity 50 (SQLite Datatype)
+* Delete special entity 99 (Work-around for the auto-increment)
+
 ### Fixed ###
 
+* Change signature of procedure `getFileIdByPath` - `FilePath TEXT` - this length is needed for the path column of `file_entities`.
+
 ### Security ###
 
 ## [5.0.0] - 2021-10-28 ##
diff --git a/libs/mytap-1.0.zip b/libs/mytap-1.0.zip
index 9e04965cd40320bde2e598c585119ffa7f6b1eab..75341f8c8f8725fca94e2a34bc3dd58e8fa8e641 100644
Binary files a/libs/mytap-1.0.zip and b/libs/mytap-1.0.zip differ
diff --git a/patches/patch20221122-6.0-SNAPSHOT/create_entity_ids_table.sql b/patches/patch20221122-6.0-SNAPSHOT/create_entity_ids_table.sql
new file mode 100644
index 0000000000000000000000000000000000000000..41297c918f0213017ebba22e1871ece2f515f782
--- /dev/null
+++ b/patches/patch20221122-6.0-SNAPSHOT/create_entity_ids_table.sql
@@ -0,0 +1,63 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2022-2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2022-2023 Timm Fitschen <t.fitschen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+-- a little bit of house keeping
+DROP PROCEDURE IF EXISTS retrieveSubEntity;
+DROP PROCEDURE IF EXISTS retrieveDatatype;
+DROP PROCEDURE IF EXISTS retrieveGroup;
+DROP PROCEDURE IF EXISTS getInfo;
+DROP PROCEDURE IF EXISTS getRole;
+DROP PROCEDURE IF EXISTS setPassword;
+DROP PROCEDURE IF EXISTS initAutoIncrement;
+DELETE FROM name_data WHERE entity_id=50;
+DELETE FROM entities WHERE id=50;
+DELETE FROM entities WHERE id=99;
+
+-- this simply is the more appropriate name
+ALTER TABLE entities MODIFY COLUMN
+  `role` enum('RECORDTYPE','RECORD','FILE','DOMAIN','PROPERTY','DATATYPE','ROLE','QUERYTEMPLATE', '_REPLACEMENT') COLLATE utf8_unicode_ci NOT NULL;
+ALTER TABLE archive_entities MODIFY COLUMN
+  `role` enum('RECORDTYPE','RECORD','FILE','DOMAIN','PROPERTY','DATATYPE','ROLE','QUERYTEMPLATE', '_REPLACEMENT') COLLATE utf8_unicode_ci NOT NULL;
+UPDATE entities SET role = "_REPLACEMENT" WHERE role="DOMAIN";
+UPDATE archive_entities SET role = "_REPLACEMENT" WHERE role="DOMAIN";
+ALTER TABLE entities MODIFY COLUMN
+  `role` enum('RECORDTYPE','RECORD','FILE','_REPLACEMENT','PROPERTY','DATATYPE','ROLE','QUERYTEMPLATE') COLLATE utf8_unicode_ci NOT NULL;
+ALTER TABLE archive_entities MODIFY COLUMN
+  `role` enum('RECORDTYPE','RECORD','FILE','_REPLACEMENT','PROPERTY','DATATYPE','ROLE','QUERYTEMPLATE') COLLATE utf8_unicode_ci NOT NULL;
+
+
+
+-- new entity_ids table
+DROP TABLE IF EXISTS `entity_ids`;
+CREATE TABLE `entity_ids` (
+    `id` VARCHAR(255) NOT NULL,
+    `internal_id` int(10) unsigned NOT NULL COMMENT 'Internal ID of an entity. This id is used internally in the *_data tables and elsewhere. This ID is never exposed via the CaosDB API.',
+    PRIMARY KEY `entity_ids_pk` (`id`),
+    CONSTRAINT `entity_ids_internal_id` FOREIGN KEY (`internal_id`) REFERENCES `entities` (`id`)
+) ENGINE=InnoDB COLLATE utf8mb4_bin;
+
+-- fill all existing entities into the new entity_ids table.
+INSERT INTO entity_ids (id, internal_id) SELECT id, id FROM entities WHERE id>0 AND role!="_REPLACEMENT";
+
+ALTER TABLE transaction_log MODIFY COLUMN `entity_id` VARCHAR(255) COLLATE utf8mb4_bin NOT NULL;
+
+ALTER TABLE user_info DROP FOREIGN KEY `subjects_ibfk_1`;
+ALTER TABle user_info MODIFY COLUMN `entity` VARCHAR(255) COLLATE utf8mb4_bin DEFAULT NULL;
+ALTER TABLE user_info ADD CONSTRAINT `subjects_ibfk_2` FOREIGN KEY (`entity`) REFERENCES `entity_ids` (`id`);
diff --git a/patches/patch20221122-6.0-SNAPSHOT/patch.sh b/patches/patch20221122-6.0-SNAPSHOT/patch.sh
new file mode 100755
index 0000000000000000000000000000000000000000..54208ab713ae9cc7bc6db8ae7501f1266e2bec86
--- /dev/null
+++ b/patches/patch20221122-6.0-SNAPSHOT/patch.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# This file is a part of the CaosDB Project.
+#
+# Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+
+# Update mysql schema to version v5.0.0
+# Drop the 'rules' table.
+
+NEW_VERSION="v6.0.0-SNAPSHOT-EXTIDS"
+OLD_VERSION="v5.0.0"
+
+if [ -z "$UTILSPATH" ]; then
+ UTILSPATH="../utils"
+fi
+
+. $UTILSPATH/patch_header.sh $*
+
+check_version $OLD_VERSION
+
+mysql_execute_file $PATCH_DIR/create_entity_ids_table.sql
+
+update_version $NEW_VERSION
+
+success
+
diff --git a/procedures/deleteEntity.sql b/procedures/deleteEntity.sql
index 5574f3e3499a0802cd9ba176904b13016e966643..f8b026d02eb48f677d2348e5f0c059b88a821d04 100644
--- a/procedures/deleteEntity.sql
+++ b/procedures/deleteEntity.sql
@@ -1,10 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020-2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -18,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 /* Delete a (sparse) Entity from the database.
@@ -31,37 +29,43 @@ have been deleted before.  This can be done for example with the
 Parameters
 ==========
 
-EntityID : UNSIGNED
-The ID of the Entity.
+EntityID : VARCHAR(255)
+    The ID of the Entity.
 */
 
 DROP PROCEDURE IF EXISTS db_5_0.deleteEntity;
 delimiter //
 
-CREATE PROCEDURE db_5_0.deleteEntity(in EntityID INT UNSIGNED)
+CREATE PROCEDURE db_5_0.deleteEntity(in EntityID VARCHAR(255))
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
     -- detele file properties
-    DELETE FROM files where file_id=EntityID;
+    DELETE FROM files where file_id=InternalEntityID;
 
     -- delete datatype stuff
     DELETE FROM data_type
         WHERE ( domain_id = 0
             AND entity_id = 0
-            AND property_id = EntityID )
-        OR datatype = EntityID;
+            AND property_id = InternalEntityID )
+        OR datatype = InternalEntityID;
     DELETE FROM collection_type
         WHERE domain_id = 0
         AND entity_id = 0
-        AND property_id = EntityID;
+        AND property_id = InternalEntityID;
 
     -- delete primary name (in case this is called without a prior call to deleteEntityProperties)
     DELETE FROM name_data
         WHERE domain_id = 0
-        AND entity_id = EntityID
+        AND entity_id = InternalEntityID
         AND property_id = 20;
 
-    DELETE FROM entities where id=EntityID;
+    DELETE FROM entity_ids
+        WHERE internal_id = InternalEntityID;
+
+    DELETE FROM entities where id=InternalEntityID;
 
     -- clean up unused acl
     DELETE FROM entity_acl
diff --git a/procedures/deleteEntityProperties.sql b/procedures/deleteEntityProperties.sql
index 147959df5f24dc8e67f1fbce97c609da1e31e09a..71b5651c58f5162752a4728c935a4a1a4ce66736 100644
--- a/procedures/deleteEntityProperties.sql
+++ b/procedures/deleteEntityProperties.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,23 +18,34 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.deleteEntityProperties;
 delimiter //
 
-CREATE PROCEDURE db_5_0.deleteEntityProperties(in EntityID INT UNSIGNED)
+/*
+ * Delete all properties of an entity (i.e. remove them from the *_data tables
+ * and the isa_cache table).
+ *
+ * Parameters
+ * ==========
+ *
+ * EntityID : VARCHAR(255)
+ *    The entity's id.
+ */
+CREATE PROCEDURE db_5_0.deleteEntityProperties(in EntityID VARCHAR(255))
 BEGIN
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
-    CALL deleteIsa(EntityID);
+    CALL deleteIsa(InternalEntityID);
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         SELECT max(e._iversion) INTO IVersion -- What's the latest version?
             FROM entity_version AS e
-            WHERE e.entity_id = EntityID;
+            WHERE e.entity_id = InternalEntityID;
 
         -- Copy the rows from *_data to archive_*_data ---------------------
         INSERT INTO archive_reference_data (domain_id, entity_id,
@@ -43,142 +53,142 @@ BEGIN
             SELECT domain_id, entity_id, property_id, value, value_iversion,
                 status, pidx, IVersion AS _iversion
             FROM reference_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_null_data (domain_id, entity_id,
                 property_id, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, status,
                 pidx, IVersion AS _iversion
             FROM null_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_text_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion
             FROM text_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_name_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion
             FROM name_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_enum_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion
             FROM enum_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_integer_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion, unit_sig)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion, unit_sig
             FROM integer_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_double_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion, unit_sig)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion, unit_sig
             FROM double_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_datetime_data (domain_id, entity_id,
                 property_id, value, value_ns, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, value, value_ns,
                 status, pidx, IVersion AS _iversion
             FROM datetime_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_date_data (domain_id, entity_id,
                 property_id, value, status, pidx, _iversion)
             SELECT domain_id, entity_id, property_id, value, status,
                 pidx, IVersion AS _iversion
             FROM date_data
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_name_overrides (domain_id, entity_id,
                 property_id, name, _iversion)
             SELECT domain_id, entity_id, property_id, name,
                 IVersion AS _iversion
             FROM name_overrides
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_desc_overrides (domain_id, entity_id,
                 property_id, description, _iversion)
             SELECT domain_id, entity_id, property_id, description,
                 IVersion AS _iversion
             FROM desc_overrides
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_data_type (domain_id, entity_id,
                 property_id, datatype, _iversion)
             SELECT domain_id, entity_id, property_id, datatype,
                 IVersion AS _iversion
             FROM data_type
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_collection_type (domain_id, entity_id,
                 property_id, collection, _iversion)
             SELECT domain_id, entity_id, property_id, collection,
                 IVersion AS _iversion
             FROM collection_type
-            WHERE (domain_id = 0 AND entity_id = EntityID)
-            OR domain_id = EntityID;
+            WHERE (domain_id = 0 AND entity_id = InternalEntityID)
+            OR domain_id = InternalEntityID;
 
         INSERT INTO archive_query_template_def (id, definition, _iversion)
             SELECT id, definition, IVersion AS _iversion
             FROM query_template_def
-            WHERE id = EntityID;
+            WHERE id = InternalEntityID;
 
     END IF;
 
     DELETE FROM reference_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM null_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM text_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM name_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM enum_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM integer_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM double_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM datetime_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM date_data
-    where (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    where (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
 
     DELETE FROM name_overrides
-    WHERE (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    WHERE (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM desc_overrides
-    WHERE (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    WHERE (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
 
     DELETE FROM data_type
-    WHERE (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    WHERE (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
     DELETE FROM collection_type
-    WHERE (domain_id=0 AND entity_id=EntityID) OR domain_id=EntityID;
+    WHERE (domain_id=0 AND entity_id=InternalEntityID) OR domain_id=InternalEntityID;
 
-    DELETE FROM query_template_def WHERE id=EntityID;
+    DELETE FROM query_template_def WHERE id=InternalEntityID;
 
 END;
 //
diff --git a/procedures/deleteIsaCache.sql b/procedures/deleteIsaCache.sql
index fd78d3fd8a23a93b91cacedbcc28f91966c59d90..dcfb68cf694458b56401720da8c939baae770247 100644
--- a/procedures/deleteIsaCache.sql
+++ b/procedures/deleteIsaCache.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 SET GLOBAL log_bin_trust_function_creators = 1;
 
@@ -38,30 +35,30 @@ parameter entity is a child or inside the rpath.
 Parameters
 ==========
 
-EntityID : UNSIGNED
-Child entity for which all parental relations should be deleted.
+InternalEntityID : UNSIGNED
+    Child entity for which all parental relations should be deleted.
 */
-CREATE PROCEDURE db_5_0.deleteIsa(IN EntityID INT UNSIGNED)
+CREATE PROCEDURE db_5_0.deleteIsa(IN InternalEntityID INT UNSIGNED)
 BEGIN
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         SELECT max(_iversion) INTO IVersion
             FROM entity_version
-            WHERE entity_id = EntityID;
+            WHERE entity_id = InternalEntityID;
 
         -- move to archive_isa before deleting
         INSERT IGNORE INTO archive_isa (child, child_iversion, parent, direct)
-            SELECT e.child, IVersion AS child_iversion, e.parent, rpath = EntityID
+            SELECT e.child, IVersion AS child_iversion, e.parent, rpath = InternalEntityID
             FROM isa_cache AS e
-            WHERE e.child = EntityID;
+            WHERE e.child = InternalEntityID;
     END IF;
 
     DELETE FROM isa_cache
-        WHERE child = EntityID
-        OR rpath = EntityID
-        OR rpath LIKE concat('%>', EntityID)
-        OR rpath LIKE concat('%>', EntityID, '>%');
+        WHERE child = InternalEntityID
+        OR rpath = InternalEntityID
+        OR rpath LIKE concat('%>', InternalEntityID)
+        OR rpath LIKE concat('%>', InternalEntityID, '>%');
 
 END;
 //
diff --git a/procedures/entityVersioning.sql b/procedures/entityVersioning.sql
index 888fc60ac4b9a821a6b8e3446f13456abad91815..b474d0121130a1695d69616e1de4cc54468b5e64 100644
--- a/procedures/entityVersioning.sql
+++ b/procedures/entityVersioning.sql
@@ -1,8 +1,8 @@
 /*
  * This file is a part of the CaosDB Project.
  *
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -27,23 +27,23 @@ DROP PROCEDURE IF EXISTS db_5_0.insert_single_child_version //
  *
  * Parameters
  * ----------
- * EntityID
- *   The ID of the versioned entity.
- * Hash
+ * InternalEntityID : INT UNSIGNED
+ *   The internal ID of the versioned entity.
+ * Hash : VARBINARY(255)
  *   A hash of the entity. This is currently not implemented properly and only
  *   there for future use.
- * Version
+ * Version : VARBINARY(255)
  *   The new version ID of the entity, must be produced by the caller.  Must be unique for each
  *   EntityID.
- * Parent
+ * Parent : VARBINARY(255)
  *   The version ID of the primary parent (i.e. predecessor).  May be NULL; but if given, it must
  *   exist.
- * Transaction
+ * Transaction : VARBINARY(255)
  *   The transaction ID which created this entity version (by inserting
  *   or updating an entity).
  */
 CREATE PROCEDURE db_5_0.insert_single_child_version(
-    in EntityID INT UNSIGNED,
+    in InternalEntityID INT UNSIGNED,
     in Hash VARBINARY(255),
     in Version VARBINARY(255),
     in Parent VARBINARY(255),
@@ -57,12 +57,12 @@ BEGIN
     IF Parent IS NOT NULL THEN
         SELECT e._iversion INTO newipparent
             FROM entity_version AS e
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
             AND e.version = Parent;
         IF newipparent IS NULL THEN
             -- throw error;
             SELECT concat("This parent does not exists: ", Parent)
-            FROM nonexisting;
+            FROM parent_version_does_not_exist;
         END IF;
     END IF;
 
@@ -70,7 +70,7 @@ BEGIN
     -- generate _iversion
     SELECT max(e._iversion)+1 INTO newiversion
         FROM entity_version AS e
-        WHERE e.entity_id=EntityID;
+        WHERE e.entity_id=InternalEntityID;
     IF newiversion IS NULL THEN
         SET newiversion = 1;
     END IF;
@@ -78,7 +78,7 @@ BEGIN
     INSERT INTO entity_version
         (entity_id, hash, version, _iversion, _ipparent, srid)
         VALUES
-        (EntityID, Hash, Version, newiversion, newipparent, Transaction);
+        (InternalEntityID, Hash, Version, newiversion, newipparent, Transaction);
 
 
 
@@ -87,22 +87,28 @@ END;
 
 DROP PROCEDURE IF EXISTS db_5_0.delete_all_entity_versions //
 
+/* THIS PROCEDURE HAS NEVER BEEN USED (outside of the tests). Reactivate when
+ * versioning's FORGET is being implemented. */
 /**
  * Remove all records in the entity_version table for the given entity.
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The id of the versioned entity.
  */
-CREATE PROCEDURE db_5_0.delete_all_entity_versions(
-    in EntityID INT UNSIGNED)
+/* CREATE PROCEDURE db_5_0.delete_all_entity_versions(
+    in EntityID VARCHAR(255))
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
 
-    DELETE FROM entity_version WHERE entity_id = EntityID;
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
+    DELETE FROM entity_version WHERE entity_id = InternalEntityID;
 
 END;
 //
+*/
 
 DROP FUNCTION IF EXISTS db_5_0.get_iversion //
 
@@ -111,9 +117,9 @@ DROP FUNCTION IF EXISTS db_5_0.get_iversion //
  *
  * Parameters
  * ----------
- * EntityID
- *   The entity's id.
- * Version
+ * InternalEntityID : INT UNSIGNED
+ *   The entity's internal id.
+ * Version : VARBINARY(255)
  *   The (official, externally used) version id.
  *
  * Returns
@@ -121,7 +127,7 @@ DROP FUNCTION IF EXISTS db_5_0.get_iversion //
  * The internal version id.
  */
 CREATE FUNCTION db_5_0.get_iversion(
-    EntityID INT UNSIGNED,
+    InternalEntityID INT UNSIGNED,
     Version VARBINARY(255))
 RETURNS INT UNSIGNED
 READS SQL DATA
@@ -129,7 +135,7 @@ BEGIN
     RETURN (
         SELECT e._iversion
             FROM entity_version AS e
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
                 AND e.version = Version
         );
 END;
@@ -143,9 +149,9 @@ DROP FUNCTION IF EXISTS db_5_0.get_primary_parent_version //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity id.
- * Version
+ * Version : VARBINARY(255)
  *   The version id.
  *
  * Returns
@@ -153,17 +159,21 @@ DROP FUNCTION IF EXISTS db_5_0.get_primary_parent_version //
  * The id of the given version's primary parent version.
  */
 CREATE FUNCTION db_5_0.get_primary_parent_version(
-    EntityID INT UNSIGNED,
+    EntityID VARCHAR(255),
     Version VARBINARY(255))
 RETURNS VARBINARY(255)
 READS SQL DATA
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
     RETURN (
         SELECT p.version
             FROM entity_version AS e INNER JOIN entity_version AS p
                 ON (e._ipparent = p._iversion
                     AND e.entity_id = p.entity_id)
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
                 AND e.version = Version
         );
 END;
@@ -177,9 +187,9 @@ DROP FUNCTION IF EXISTS db_5_0.get_version_timestamp //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity id.
- * Version
+ * Version : VARBINARY(255)
  *   The version id.
  *
  * Returns
@@ -188,16 +198,20 @@ DROP FUNCTION IF EXISTS db_5_0.get_version_timestamp //
  * Note that the dot `.` here is not necessarily a decimal separator.
  */
 CREATE FUNCTION db_5_0.get_version_timestamp(
-    EntityID INT UNSIGNED,
+    EntityID VARCHAR(255),
     Version VARBINARY(255))
 RETURNS VARCHAR(255)
 READS SQL DATA
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
     RETURN (
         SELECT concat(t.seconds, '.', t.nanos)
             FROM entity_version AS e INNER JOIN transactions AS t
                 ON ( e.srid = t.srid )
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
             AND e.version = Version
     );
 END;
@@ -210,7 +224,7 @@ DROP FUNCTION IF EXISTS db_5_0.get_head_version //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity id.
  *
  * Returns
@@ -218,7 +232,7 @@ DROP FUNCTION IF EXISTS db_5_0.get_head_version //
  * The version id of the HEAD.
  */
 CREATE FUNCTION db_5_0.get_head_version(
-    EntityID INT UNSIGNED)
+    EntityID VARCHAR(255))
 RETURNS VARBINARY(255)
 READS SQL DATA
 BEGIN
@@ -233,15 +247,15 @@ DROP FUNCTION IF EXISTS db_5_0._get_head_iversion //
  *
  * Parameters
  * ----------
- * EntityID
- *   The entity id.
+ * InternalEntityID : INT UNSIGNED
+ *   The entity's internal id.
  *
  * Returns
  * -------
  * The _iversion of the HEAD.
  */
 CREATE FUNCTION db_5_0._get_head_iversion(
-    EntityID INT UNSIGNED)
+    InternalEntityID INT UNSIGNED)
 RETURNS INT UNSIGNED
 READS SQL DATA
 BEGIN
@@ -252,7 +266,7 @@ BEGIN
     RETURN (
         SELECT e._iversion
             FROM entity_version AS e
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
             ORDER BY e._iversion DESC
             LIMIT 1
         );
@@ -267,9 +281,9 @@ DROP FUNCTION IF EXISTS db_5_0.get_head_relative //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity id.
- * Offset
+ * Offset : INT UNSIGNED
  *   Distance in the sequence of primary parents of the entity. E.g. `0` is the
  *   HEAD itself. `1` is the primary parent of the HEAD. `2` is the primary
  *   parent of the primary parent of the HEAD, and so on.
@@ -279,11 +293,15 @@ DROP FUNCTION IF EXISTS db_5_0.get_head_relative //
  * The version id of the HEAD.
  */
 CREATE FUNCTION db_5_0.get_head_relative(
-    EntityID INT UNSIGNED,
+    EntityID VARCHAR(255),
     Offset INT UNSIGNED)
 RETURNS VARBINARY(255)
 READS SQL DATA
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
     -- This implementation assumes that the distance from the head equals the
     -- difference between the _iversion numbers. This will not be correct anymore
     -- as soon as branches may split and merge. Then, a walk over the primary
@@ -291,7 +309,7 @@ BEGIN
     RETURN (
         SELECT e.version
             FROM entity_version AS e
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
             ORDER BY e._iversion DESC
             LIMIT 1 OFFSET Offset
         );
@@ -304,24 +322,24 @@ DROP FUNCTION IF EXISTS db_5_0._get_version //
  *
  * Parameters
  * ----------
- * EntityID
- *   The entity id.
+ * InternalEntityID : INT UNSIGNED
+ *   The entity's internal id.
  * IVersion
  *   Internal version id (integer).
  *
  * Returns
  * -------
- * The version id.
+ * The (external) version id.
  */
 CREATE FUNCTION db_5_0._get_version(
-    EntityID INT UNSIGNED,
+    InternalEntityID INT UNSIGNED,
     IVersion INT UNSIGNED)
 RETURNS VARBINARY(255)
 READS SQL DATA
 BEGIN
     RETURN (
         SELECT version FROM entity_version
-            WHERE entity_id = EntityID
+            WHERE entity_id = InternalEntityID
             AND _iversion = IVersion
         );
 END;
@@ -335,7 +353,7 @@ DROP PROCEDURE IF EXISTS db_5_0.get_version_history //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity id.
  *
  * Selects
@@ -344,8 +362,12 @@ DROP PROCEDURE IF EXISTS db_5_0.get_version_history //
  *   child_realm). `child` and `parent` are version IDs.
  */
 CREATE PROCEDURE db_5_0.get_version_history(
-    in EntityID INT UNSIGNED)
+    in EntityID VARCHAR(255))
 BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
     -- retrieve root(s) (initial versions)
     SELECT c.version AS child,
             NULL as parent,
@@ -355,7 +377,7 @@ BEGIN
             t.realm AS child_realm
         FROM entity_version AS c INNER JOIN transactions as t
         ON ( c.srid = t.srid )
-        WHERE c.entity_id = EntityID
+        WHERE c.entity_id = InternalEntityID
         AND c._ipparent is Null
 
     -- TODO This first SELECT statement is necessary because the second one
@@ -375,7 +397,7 @@ BEGIN
             ON (c._ipparent = p._iversion
                 AND c.entity_id = p.entity_id
                 AND t.srid = c.srid)
-        WHERE p.entity_id = EntityID;
+        WHERE p.entity_id = InternalEntityID;
 END;
 //
 
@@ -412,56 +434,6 @@ BEGIN
 END //
 
 
-
-DROP PROCEDURE IF EXISTS setFileProperties //
-/**
- * Insert/Update file properties.
- *
- * If ENTITY_VERSIONING is enabled the old file properties are moved to
- * `archive_files`.
- *
- * Parameters
- * ----------
- * EntityID
- *   The file's id.
- * FilePath
- *   Path of the file in the internal file system.  If NULL, an existing file
- *   entity is simply deleted.
- * FileSize
- *   Size of the file in bytes.
- * FileHash
- *   A Sha512 Hash of the file.
- */
-CREATE PROCEDURE setFileProperties (
-    in EntityID INT UNSIGNED,
-    in FilePath TEXT,
-    in FileSize BIGINT UNSIGNED,
-    in FileHash VARCHAR(255)
-)
-BEGIN
-    DECLARE IVersion INT UNSIGNED DEFAULT NULL;
-    IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
-        SELECT max(e._iversion) INTO IVersion
-            FROM entity_version AS e
-            WHERE e.entity_id = EntityID;
-
-        INSERT INTO archive_files (file_id, path, size, hash,
-                _iversion)
-            SELECT file_id, path, size, hash, IVersion AS _iversion
-            FROM files
-            WHERE file_id = EntityID;
-    END IF;
-
-    DELETE FROM files WHERE file_id = EntityID;
-
-    IF FilePath IS NOT NULL THEN
-        INSERT INTO files (file_id, path, size, hash)
-            VALUES (EntityID, FilePath, FileSize, unhex(FileHash));
-    END IF;
-
-END //
-
-
 DROP PROCEDURE IF EXISTS retrieveQueryTemplateDef //
 
 /**
@@ -469,9 +441,9 @@ DROP PROCEDURE IF EXISTS retrieveQueryTemplateDef //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The QueryTemplate's id.
- * Version
+ * Version : VARBINARY(255)
  *   The QueryTemplate's version's id.
  *
  * Returns
@@ -480,12 +452,16 @@ DROP PROCEDURE IF EXISTS retrieveQueryTemplateDef //
  * QueryTemplate.
  */
 CREATE PROCEDURE retrieveQueryTemplateDef (
-    in EntityID INT UNSIGNED,
+    in EntityID VARCHAR(255),
     in Version VARBINARY(255))
 retrieveQueryTemplateDefBody: BEGIN
 
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
     DECLARE IsHead BOOLEAN DEFAULT TRUE;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         -- Are we at the head?
@@ -494,11 +470,7 @@ retrieveQueryTemplateDefBody: BEGIN
         END IF;
 
         IF IsHead IS FALSE THEN
-            -- TODO Use get_iversion(EntityID, Version) instead?  Or will that be much slower?
-            SELECT e._iversion INTO IVersion
-                FROM entity_version as e
-                WHERE e.entity_id = EntityID
-                AND e.version = Version;
+            SET IVersion = get_iversion(InternalEntityID, Version);
 
             IF IVersion IS NULL THEN
                 -- RETURN EARLY - Version does not exist.
@@ -507,7 +479,7 @@ retrieveQueryTemplateDefBody: BEGIN
 
             SELECT definition
             FROM archive_query_template_def
-            WHERE id = EntityID
+            WHERE id = InternalEntityID
             AND _iversion = IVersion;
 
             LEAVE retrieveQueryTemplateDefBody;
@@ -516,7 +488,7 @@ retrieveQueryTemplateDefBody: BEGIN
 
     SELECT definition
     FROM query_template_def
-    WHERE id = EntityID;
+    WHERE id = InternalEntityID;
 
 END //
 
diff --git a/procedures/getDependentEntities.sql b/procedures/getDependentEntities.sql
index 708503d90954c8ecea1fafa67113b7130a7b6684..0940e440661c0d73f2eea03e3e10d10082c9eb9e 100644
--- a/procedures/getDependentEntities.sql
+++ b/procedures/getDependentEntities.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <www.indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -18,56 +19,76 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  *
- * ** end header
  */
 
 
-
 DROP PROCEDURE IF EXISTS db_5_0.getDependentEntities;
 delimiter //
 
-CREATE PROCEDURE db_5_0.getDependentEntities(in EntityID INT UNSIGNED)
+/*
+ * Return all entities which either reference the given entity, use the given
+ * reference as data type, or are direct children of the given entity.
+ *
+ * This function used to make sure that no entity can be deleted which
+ * is still needed by others.
+ *
+ * Parameters
+ * ----------
+ * EntityID : VARCHAR(255)
+ *    The entity id.
+ *
+ * ResultSet
+ * ---------
+ * EntityID : VARCHAR(255)
+ *
+ */
+CREATE PROCEDURE db_5_0.getDependentEntities(in EntityID VARCHAR(255))
 BEGIN
 
-DROP TEMPORARY TABLE IF EXISTS refering;		
-CREATE TEMPORARY TABLE refering (
-id INT UNSIGNED UNIQUE
-);
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    DROP TEMPORARY TABLE IF EXISTS referring;
+    CREATE TEMPORARY TABLE referring (
+        id INT UNSIGNED UNIQUE
+    );
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM reference_data WHERE (value=EntityID OR property_id=EntityID) AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM reference_data WHERE (value=EntityID OR property_id=EntityID) AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM reference_data WHERE (value=InternalEntityID OR property_id=InternalEntityID) AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM reference_data WHERE (value=InternalEntityID OR property_id=InternalEntityID) AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM text_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM text_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM text_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM text_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM enum_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM enum_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM enum_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM enum_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM name_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM name_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM name_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM name_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM integer_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM integer_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM integer_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM integer_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM double_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM double_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM double_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM double_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM datetime_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM datetime_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM datetime_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM datetime_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM date_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM date_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM date_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM date_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id FROM null_data WHERE property_id=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id FROM null_data WHERE property_id=EntityID AND domain_id!=EntityID AND entity_id!=EntityID AND domain_id!=0; 
+    INSERT IGNORE INTO referring (id) SELECT entity_id FROM null_data WHERE property_id=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id FROM null_data WHERE property_id=InternalEntityID AND domain_id!=InternalEntityID AND entity_id!=InternalEntityID AND domain_id!=0;
 
-INSERT IGNORE INTO refering (id) SELECT entity_id from data_type WHERE datatype=EntityID AND domain_id=0 AND entity_id!=EntityID;
-INSERT IGNORE INTO refering (id) SELECT domain_id from data_type WHERE datatype=EntityID;
+    INSERT IGNORE INTO referring (id) SELECT entity_id from data_type WHERE datatype=InternalEntityID AND domain_id=0 AND entity_id!=InternalEntityID;
+    INSERT IGNORE INTO referring (id) SELECT domain_id from data_type WHERE datatype=InternalEntityID;
 
+    INSERT IGNORE INTO referring (id) SELECT child FROM isa_cache WHERE parent = InternalEntityID AND rpath = child;
 
-Select id from refering WHERE id!=0 and id!=EntityID;
+    SELECT e.id FROM referring AS r LEFT JOIN entity_ids AS e ON r.id = e.internal_id WHERE r.id!=0 AND e.internal_id!=InternalEntityID;
 
-DROP TEMPORARY TABLE refering;
+    DROP TEMPORARY TABLE referring;
 
 END;
 //
diff --git a/procedures/getFileIdByPath.sql b/procedures/getFileIdByPath.sql
index e565eced5b7fac23199d2ce9169fe45822dfffbc..07e7b8bcb57c61f4ff8f155537bf0d5bb8307820 100644
--- a/procedures/getFileIdByPath.sql
+++ b/procedures/getFileIdByPath.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,16 +18,27 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 Drop Procedure if exists db_5_0.getFileIdByPath;
 Delimiter //
-Create Procedure db_5_0.getFileIdByPath (in FilePath VARCHAR(255))
-BEGIN 
 
-Select file_id as FileID from files where path=FilePath LIMIT 1;
+/*
+ * Return a file's id for a given path or nothing if the path is unknown.
+ *
+ * Parameters
+ * ----------
+ * FilePath : TEXT
+ *    The file's path.
+ *
+ * Returns
+ * -------
+ * EntityID : VARCHAR(255)
+ */
+Create Procedure db_5_0.getFileIdByPath (in FilePath TEXT)
+BEGIN
+
+    SELECT e.id AS FileID FROM files AS f LEFT JOIN entity_ids ON e.internal_in = f.file_id WHERE f.path=FilePath LIMIT 1;
 
 END;
 //
diff --git a/procedures/getIdByName.sql b/procedures/getIdByName.sql
new file mode 100644
index 0000000000000000000000000000000000000000..781594eff9fba3b3582e2e2a4a828f3c7a98a10c
--- /dev/null
+++ b/procedures/getIdByName.sql
@@ -0,0 +1,63 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+DROP PROCEDURE IF EXISTS db_5_0.getIdByName;
+DELIMITER //
+
+/*
+ * Return the Entity id(s) for a given name. Optionally, filter by role and set
+ * a limit.
+ *
+ * Parameters
+ * ----------
+ * Name : VARCHAR(255)
+ *    The entity's name.
+ * Role : VARCHAR(255)
+ *    E.g. RecordType, Record, Property,...
+ * Lmt : INT UNSIGNED
+ *    Limit the number of returned entity ids.
+ *
+ * Returns
+ * -------
+ * EntityID : VARCHAR(255)
+ */
+CREATE PROCEDURE db_5_0.getIdByName(in Name VARCHAR(255), in Role VARCHAR(255), in Lmt INT UNSIGNED)
+BEGIN
+
+    SET @stmtStr = "SELECT e.id AS id FROM name_data AS n JOIN entity_ids AS e ON (n.domain_id=0 AND n.property_id=20 AND e.internal_id = n.entity_id) JOIN entities AS i ON (i.id = e.internal_id) WHERE n.value = ?";
+
+    IF Role IS NULL THEN
+        SET @stmtStr = CONCAT(@stmtStr, " AND i.role!='ROLE'");
+    ELSE
+        SET @stmtStr = CONCAT(@stmtStr, " AND i.role='", Role, "'");
+    END IF;
+
+    IF Lmt IS NOT NULL THEN
+        SET @stmtStr = CONCAT(@stmtStr, " LIMIT ", Lmt);
+    END IF;
+
+    SET @vName = Name;
+    PREPARE stmt FROM @stmtStr;
+    EXECUTE stmt USING @vName;
+    DEALLOCATE PREPARE stmt;
+
+END;
+//
+DELIMITER ;
diff --git a/procedures/getInfo.sql b/procedures/getInfo.sql
deleted file mode 100644
index 03c75b4e1df37400596c85d20e5421abc43c6f10..0000000000000000000000000000000000000000
--- a/procedures/getInfo.sql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-#-- old procedure.
-Drop Procedure if exists db_5_0.getInfo;
diff --git a/procedures/getRole.sql b/procedures/getRole.sql
deleted file mode 100644
index bea96fcfbf14d7ad8ec62b88c272ab22c5d94258..0000000000000000000000000000000000000000
--- a/procedures/getRole.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-
-
-
-
-
-
-
-DROP PROCEDURE IF EXISTS db_5_0.getRole;
-delimiter //
-CREATE PROCEDURE db_5_0.getRole(in RoleName VARCHAR(255))
-BEGIN
-
-Select e.id INTO @RoleID from entities e where e.name=RoleName AND e.role=RoleName LIMIT 1;
-
-call retrieveEntity(@RoleID);
-
-
-
-
-END;
-//
-delimiter ;
diff --git a/procedures/initAutoIncrement.sql b/procedures/initAutoIncrement.sql
deleted file mode 100644
index 54cb54525ee7d8b864c1e979dfda6ab9471fcfb5..0000000000000000000000000000000000000000
--- a/procedures/initAutoIncrement.sql
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-
-DROP PROCEDURE IF EXISTS db_5_0.initAutoIncrement;
-delimiter //
-
-CREATE PROCEDURE db_5_0.initAutoIncrement()
-BEGIN
-
-    SELECT @max := MAX(entity_id)+ 1 FROM transaction_log; 
-    IF @max IS NOT NULL THEN
-        SET @stmtStr = CONCAT('ALTER TABLE entities AUTO_INCREMENT=',@max);
-        PREPARE stmt FROM @stmtStr;
-        EXECUTE stmt;
-        DEALLOCATE PREPARE stmt;
-    END IF;
-
-END;
-//
-delimiter ;
diff --git a/procedures/insertEntity.sql b/procedures/insertEntity.sql
index e73a3bd8acc9ac7ad27f9b261c780a10939d8e8c..816fe8bae65c8a92569d4229993815d6ac0634af 100644
--- a/procedures/insertEntity.sql
+++ b/procedures/insertEntity.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
@@ -31,12 +28,14 @@ delimiter //
 Parameters
 ==========
 
+EntityID : VARCHAR(255)
+    The entity id.
 EntityName : VARCHAR(255)
 
 EntityDesc : TEXT
 
 EntityRole : VARCHAR(255)
-Currently one of 'RECORDTYPE', 'RECORD', 'FILE', 'DOMAIN', 'PROPERTY',
+Currently one of 'RECORDTYPE', 'RECORD', 'FILE', 'PROPERTY',
 'DATATYPE', 'ROLE', 'QUERYTEMPLATE'
 
 ACL : VARBINARY(65525)
@@ -44,17 +43,17 @@ ACL : VARBINARY(65525)
 Select
 ======
 
-A tuple (EntityID, Version)
+(Version)
 */
-CREATE PROCEDURE db_5_0.insertEntity(in EntityName VARCHAR(255), in EntityDesc TEXT, in EntityRole VARCHAR(255), in ACL VARBINARY(65525))
+CREATE PROCEDURE db_5_0.insertEntity(in EntityID VARCHAR(255), in EntityName VARCHAR(255), in EntityDesc TEXT, in EntityRole VARCHAR(255), in ACL VARBINARY(65525))
 BEGIN
-    DECLARE NewEntityID INT UNSIGNED DEFAULT NULL;
     DECLARE NewACLID INT UNSIGNED DEFAULT NULL;
     DECLARE Hash VARBINARY(255) DEFAULT NULL;
     DECLARE Version VARBINARY(255) DEFAULT NULL;
     DECLARE Transaction VARBINARY(255) DEFAULT NULL;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
 
-    -- insert the acl. the new acl id is being written (c-style) into the
+    -- insert the acl. The new acl id is written (c-style) into the
     -- variable NewACLID.
     call entityACL(NewACLID, ACL);
 
@@ -63,13 +62,15 @@ BEGIN
         VALUES (EntityDesc, EntityRole, NewACLID);
 
     -- ... and return the generated id
-    SET NewEntityID = LAST_INSERT_ID();
+    SET InternalEntityID = LAST_INSERT_ID();
+
+    INSERT INTO entity_ids (internal_id, id) VALUES (InternalEntityID, EntityID);
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         -- TODO this is transaction-scoped variable. Is this a good idea?
         SET Transaction = @SRID;
         SET Version = SHA1(UUID());
-        CALL insert_single_child_version(NewEntityID, Hash, Version, Null, Transaction);
+        CALL insert_single_child_version(InternalEntityID, Hash, Version, Null, Transaction);
     END IF;
 
     -- insert the name of the entity into name_data table
@@ -77,10 +78,10 @@ BEGIN
     IF EntityName IS NOT NULL THEN
         INSERT INTO name_data
             (domain_id, entity_id, property_id, value, status, pidx)
-            VALUES (0, NewEntityID, 20, EntityName, "FIX", 0);
+            VALUES (0, InternalEntityID, 20, EntityName, "FIX", 0);
     END IF;
 
-    SELECT NewEntityID as EntityID, Version as Version;
+    SELECT Version as Version;
 
 END;
 //
diff --git a/procedures/insertEntityDataType.sql b/procedures/insertEntityDataType.sql
new file mode 100644
index 0000000000000000000000000000000000000000..78df168f72972a2ccc8dd95792e9849d0715aaf9
--- /dev/null
+++ b/procedures/insertEntityDataType.sql
@@ -0,0 +1,71 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+DROP PROCEDURE IF EXISTS db_5_0.insertEntityDataType;
+DELIMITER //
+
+/*
+ * Insert the (default) datatype of a property.
+ *
+ * Parameters
+ * ----------
+ * PropertyID : VARCHAR(255)
+ *   The property id.
+ * DataType : VARCHAR(255)
+ *   The data type, e.g. "DOUBLE", "Person"
+ */
+CREATE PROCEDURE db_5_0.insertEntityDataType(in PropertyID VARCHAR(255), in DataType VARCHAR(255))
+BEGIN
+    DECLARE InternalPropertyID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalPropertyID FROM entity_ids WHERE id=PropertyID;
+
+    INSERT INTO data_type (domain_id, entity_id, property_id, datatype) SELECT 0, 0, InternalPropertyID, ( SELECT entity_id FROM name_data WHERE domain_id = 0 AND property_id = 20 AND value = DataType LIMIT 1);
+
+
+END;
+//
+DELIMITER ;
+
+
+DROP PROCEDURE IF EXISTS db_5_0.insertEntityCollection;
+DELIMITER //
+
+/*
+ * Insert the (default) collection type of a property.
+ *
+ * Parameters
+ * ----------
+ * PropertyID : VARCHAR(255)
+ *   The property id.
+ * Collection : VARCHAR(255)
+ *   The collection, e.g. "LIST"
+ */
+CREATE PROCEDURE db_5_0.insertEntityCollection(in PropertyID VARCHAR(255), in Collection VARCHAR(255))
+BEGIN
+    DECLARE InternalPropertyID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalPropertyID FROM entity_ids WHERE id=PropertyID;
+
+    INSERT INTO collection_type (domain_id, entity_id, property_id, collection) SELECT 0, 0, InternalPropertyID, Collection;
+
+END;
+//
+DELIMITER ;
diff --git a/procedures/insertEntityProperty.sql b/procedures/insertEntityProperty.sql
index 1cfd38bac3f0bd455779d7398d46f3dcf3df1243..ee26c168612cacf93f19576e21e36d23ff4270ca 100644
--- a/procedures/insertEntityProperty.sql
+++ b/procedures/insertEntityProperty.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,112 +18,153 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.insertEntityProperty;
 delimiter //
+
+
+/*
+ * Insert the property of an entity (level 1 and 2, only one *_data table entry at a time).
+ *
+ * Parameters
+ * ----------
+ * DomainID : VARCHAR(255)
+ *     The domain id (0 or the entity's id for level-2-data)
+ * EntityID : VARCHAR(255)
+ *     The entity id (or the property's id for level-2-data)
+ * PropertyID : VARCHAR(255)
+ *     The property id (or the sub-property's id for level-2-data)
+ * Datatable : VARCHAR(255)
+ *     Name of the *_data table, e.g. 'double_data'.
+ * PropertyValue : TEXT
+ *     The property's value
+ * PropertyUnitSig : BIGINT
+ *     The unit signature.
+ * PropertyStatus : VARCHAR(255)
+ *     E.g. OBLIGATORY, FIX,...
+ * NameOverride : VARCHAR(255)
+ *     The overridden name
+ * DescOverride : TEXT
+ *     The overridden description
+ * DatatypeOverride : VARCHAR(255)
+ *     The overridden datatype
+ * Collection : VARCHAR(255)
+ *     The overridden collection (only if DatatypeOverride is present).
+ * PropertyIndex : INT UNSIGNED
+ *     The property's index (for ordering of properties and values).
+ */
 CREATE PROCEDURE db_5_0.insertEntityProperty(
-    in DomainID INT UNSIGNED,
-    in EntityID INT UNSIGNED,
-    in PropertyID INT UNSIGNED,
+    in DomainID VARCHAR(255),
+    in EntityID VARCHAR(255),
+    in PropertyID VARCHAR(255),
     in Datatable VARCHAR(255),
     in PropertyValue TEXT,
     in PropertyUnitSig BIGINT,
     in PropertyStatus VARCHAR(255),
     in NameOverride VARCHAR(255),
     in DescOverride TEXT,
-    in DatatypeOverride INT UNSIGNED,
+    in DatatypeOverride VARCHAR(255),
     in Collection VARCHAR(255),
     in PropertyIndex INT UNSIGNED)
 BEGIN
     DECLARE ReferenceValueIVersion INT UNSIGNED DEFAULT NULL;
     DECLARE ReferenceValue INT UNSIGNED DEFAULT NULL;
     DECLARE AT_PRESENT INTEGER DEFAULT NULL;
+    DECLARE InternalDataTypeID INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalPropertyID INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalDomainID INT UNSIGNED DEFAULT 0;
+
+    SELECT temp.internal_id INTO InternalDomainID FROM (SELECT internal_id AS internal_id FROM entity_ids WHERE id = DomainID UNION SELECT DomainID AS internal_id) AS temp LIMIT 1;
+    SELECT temp.internal_id INTO InternalEntityID FROM (SELECT internal_id AS internal_id FROM entity_ids WHERE id = EntityID UNION SELECT EntityID AS internal_id) AS temp LIMIT 1;
+    SELECT temp.internal_id INTO InternalPropertyID FROM (SELECT internal_id AS internal_id FROM entity_ids WHERE id = PropertyID UNION SELECT PropertyID AS internal_id) AS temp LIMIT 1;
 
     CASE Datatable
     WHEN 'double_data' THEN
         INSERT INTO double_data
         (domain_id, entity_id, property_id, value, unit_sig, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyValue, PropertyUnitSig, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyValue, PropertyUnitSig, PropertyStatus, PropertyIndex);
     WHEN 'integer_data' THEN
         INSERT INTO integer_data
         (domain_id, entity_id, property_id, value, unit_sig, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyValue, PropertyUnitSig, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyValue, PropertyUnitSig, PropertyStatus, PropertyIndex);
     WHEN 'datetime_data' THEN
         INSERT INTO datetime_data
         (domain_id, entity_id, property_id, value, value_ns, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, SUBSTRING_INDEX(PropertyValue, 'UTC', 1), IF(SUBSTRING_INDEX(PropertyValue, 'UTC', -1)='',NULL,SUBSTRING_INDEX(PropertyValue, 'UTC', -1)), PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, SUBSTRING_INDEX(PropertyValue, 'UTC', 1), IF(SUBSTRING_INDEX(PropertyValue, 'UTC', -1)='',NULL,SUBSTRING_INDEX(PropertyValue, 'UTC', -1)), PropertyStatus, PropertyIndex);
     WHEN 'reference_data' THEN
 
         -- special handling if versioning enabled and specific version of referenced entity is given.
         SET AT_PRESENT=LOCATE("@", PropertyValue);
         IF is_feature_config("ENTITY_VERSIONING", "ENABLED") AND AT_PRESENT > 0 THEN
-            SET ReferenceValue = SUBSTRING_INDEX(PropertyValue, '@', 1);
+            SELECT internal_id INTO ReferenceValue FROM entity_ids WHERE id = SUBSTRING_INDEX(PropertyValue, '@', 1);
             SET ReferenceValueIVersion = get_iversion(ReferenceValue,
                 SUBSTRING_INDEX(PropertyValue, '@', -1));
-            -- TODO raise error when @ present but iversion is null
             IF ReferenceValueIVersion IS NULL THEN
+                -- Raise error when @ present but iversion is null
                 SELECT 0 from `ReferenceValueIVersion_WAS_NULL`;
             END IF;
 
         ELSE
-            SET ReferenceValue = PropertyValue;
+            SELECT temp.internal_id INTO ReferenceValue FROM (SELECT internal_id AS internal_id FROM entity_ids WHERE id = PropertyValue UNION SELECT PropertyValue AS internal_id) AS temp LIMIT 1;
         END IF;
 
+
         INSERT INTO reference_data
             (domain_id, entity_id, property_id, value, value_iversion, status,
                 pidx)
         VALUES
-            (DomainID, EntityID, PropertyID, ReferenceValue,
+            (InternalDomainID, InternalEntityID, InternalPropertyID, ReferenceValue,
                 ReferenceValueIVersion, PropertyStatus, PropertyIndex);
     WHEN 'enum_data' THEN
         INSERT INTO enum_data
         (domain_id, entity_id, property_id, value, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyValue, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyValue, PropertyStatus, PropertyIndex);
     WHEN 'date_data' THEN
         INSERT INTO date_data
         (domain_id, entity_id, property_id, value, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, SUBSTRING_INDEX(PropertyValue, '.', 1), PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, SUBSTRING_INDEX(PropertyValue, '.', 1), PropertyStatus, PropertyIndex);
     WHEN 'text_data' THEN
         INSERT INTO text_data
         (domain_id, entity_id, property_id, value, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyValue, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyValue, PropertyStatus, PropertyIndex);
     WHEN 'null_data' THEN
         INSERT INTO null_data
         (domain_id, entity_id, property_id, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyStatus, PropertyIndex);
     WHEN 'name_data' THEN
         INSERT INTO name_data
         (domain_id, entity_id, property_id, value, status, pidx)
         VALUES
-        (DomainID, EntityID, PropertyID, PropertyValue, PropertyStatus, PropertyIndex);
+        (InternalDomainID, InternalEntityID, InternalPropertyID, PropertyValue, PropertyStatus, PropertyIndex);
 
     ELSE
+        -- raise error
         SELECT * FROM table_does_not_exist;
     END CASE;
 
     IF DatatypeOverride IS NOT NULL THEN
-        call overrideType(DomainID, EntityID, PropertyID, DatatypeOverride);
+        SELECT internal_id INTO InternalDataTypeID from entity_ids WHERE id = DatatypeOverride;
+        call overrideType(InternalDomainID, InternalEntityID, InternalPropertyID, InternalDataTypeID);
         IF Collection IS NOT NULL THEN
-            INSERT INTO collection_type (domain_id, entity_id, property_id, collection) VALUES (DomainID, EntityID, PropertyID, Collection);
+            INSERT INTO collection_type (domain_id, entity_id, property_id, collection) VALUES (InternalDomainID, InternalEntityID, InternalPropertyID, Collection);
         END IF;
     END IF;
 
     IF NameOverride IS NOT NULL THEN
-        call overrideName(DomainID, EntityID, PropertyID, NameOverride);
+        call overrideName(InternalDomainID, InternalEntityID, InternalPropertyID, NameOverride);
     END IF;
 
     IF DescOverride IS NOT NULL THEN
-        call overrideDesc(DomainID, EntityID, PropertyID, DescOverride);
+        call overrideDesc(InternalDomainID, InternalEntityID, InternalPropertyID, DescOverride);
     END IF;
 
 END;
diff --git a/procedures/insertIsaCache.sql b/procedures/insertIsaCache.sql
index 9d1bf1c529e8b33d33cd6c6eb794afc09e65dbea..f08ff610c9cb68fcfde4a305b770a3ba254f5329 100644
--- a/procedures/insertIsaCache.sql
+++ b/procedures/insertIsaCache.sql
@@ -1,10 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -18,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 DROP PROCEDURE IF EXISTS db_5_0.insertIsa;
 DELIMITER //
@@ -32,16 +30,22 @@ DELIMITER //
  *
  * Parameters
  * ==========
- * 
- * c : UNSIGNED
- * The child entity
- * 
- * p : UNSIGNED
- * The parent entity
+ *
+ * ChildID : VARCHAR(255)
+ *     The child entity.
+ *
+ * ParentID : VARCHAR(255)
+ *     The parent entity.
  */
-CREATE PROCEDURE db_5_0.insertIsa(IN c INT UNSIGNED, IN p INT UNSIGNED)
+CREATE PROCEDURE db_5_0.insertIsa(IN ChildID VARCHAR(255), IN ParentID VARCHAR(255))
 insert_is_a_proc: BEGIN
 
+    DECLARE c INT UNSIGNED DEFAULT NULL;
+    DECLARE p INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO c FROM entity_ids WHERE id = ChildID;
+    SELECT internal_id INTO p FROM entity_ids WHERE id = ParentID;
+
     INSERT INTO isa_cache (child, parent, rpath) VALUES (c, p, c);
 
     IF p = c THEN
@@ -69,17 +73,17 @@ insert_is_a_proc: BEGIN
     INSERT IGNORE INTO isa_cache SELECT
         l.child,    -- Descendant as found in isa_cache
         r.parent,   -- Ancestor as found in isa_cache
-        if(l.rpath=l.child and r.rpath=c,  -- if distance=1 for left and right:
+        IF(l.rpath=l.child AND r.rpath=c,  -- if distance=1 for left and right:
            c,                              -- rpath = current child
-           concat(if(l.rpath=l.child,        -- if dist=1 for descendant:
+           concat(IF(l.rpath=l.child,        -- if dist=1 for descendant:
                      c,                         -- rpath starts with c
                      concat(l.rpath, '>', c)),  -- rpath starts with "desc.rpath > c"
-                  if(r.rpath=c,              -- if dist=1 for ancestor
+                  IF(r.rpath=c,              -- if dist=1 for ancestor
                      '',                        -- rpath is finished
                      concat('>', r.rpath))))    -- rpath continuees with " > ancest.rpath"
             AS rpath
         FROM
-            isa_cache as l INNER JOIN isa_cache as r
+            isa_cache AS l INNER JOIN isa_cache AS r
             ON (l.parent = c AND c = r.child AND l.child != l.parent); -- Left: descendants of c, right: ancestors
 
 END;
diff --git a/procedures/isSubtype.sql b/procedures/isSubtype.sql
index f97c13f8f6ac75900ceca96e12cb285979a90a28..3a25612ef5121b4d644555e7a81b05f5ac0750b3 100644
--- a/procedures/isSubtype.sql
+++ b/procedures/isSubtype.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,18 +18,37 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
 DROP PROCEDURE IF EXISTS db_5_0.isSubtype;
 delimiter //
 
-CREATE PROCEDURE db_5_0.isSubtype(in c INT UNSIGNED, in p INT UNSIGNED)
+/*
+ * Return TRUE if the given Child is indeed a (direct or indirect) child of the
+ * given Parent.
+ *
+ * Parameters
+ * ----------
+ * ChildID : VARCHAR(255)
+ *     The entity id of the child.
+ * ParentID : VARCHAR(255)
+ *     The entity id of the parent.
+ *
+ * Returns
+ * -------
+ * ISA : BOOLEAN
+ */
+CREATE PROCEDURE db_5_0.isSubtype(in ChildID VARCHAR(255), in ParentID VARCHAR(255))
 BEGIN
-	DECLARE ret BOOLEAN DEFAULT FALSE;
-	SELECT TRUE INTO ret FROM isa_cache AS i WHERE i.child=c AND i.parent=p LIMIT 1;
+    DECLARE c INT UNSIGNED DEFAULT NULL;
+    DECLARE p INT UNSIGNED DEFAULT NULL;
+    DECLARE ret BOOLEAN DEFAULT FALSE;
+
+    SELECT internal_id INTO c from entity_ids WHERE id = ChildID;
+    SELECT internal_id INTO p from entity_ids WHERE id = ParentID;
+
+    SELECT TRUE INTO ret FROM isa_cache AS i WHERE i.child=c AND i.parent=p LIMIT 1;
     SELECT ret as ISA;
 END;
 //
diff --git a/procedures/overrideName.sql b/procedures/overrideName.sql
index ace102b25a72f0f4159a0769efce4209449d5bc4..cbd74fd00de550630e8a402b048cbc242479389c 100644
--- a/procedures/overrideName.sql
+++ b/procedures/overrideName.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.overrideName;
@@ -26,21 +25,61 @@ DROP PROCEDURE IF EXISTS db_5_0.overrideDesc;
 DROP PROCEDURE IF EXISTS db_5_0.overrideType;
 
 DELIMITER //
-CREATE PROCEDURE db_5_0.overrideName(in DomainID INT UNSIGNED, in EntityID INT UNSIGNED, in PropertyID INT UNSIGNED, in Name VARCHAR(255))
+/*
+ * Insert a name override.
+ *
+ * Parameters
+ * ----------
+ * InternalDomainID : INT UNSIGNED
+ *     The *internal* id of the domain.
+ * InternalEntityID : INT UNSIGNED
+ *     The *internal* id of the entity.
+ * InternalPropertyID : INT UNSIGNED
+ *     The *internal* id of the property.
+ * Name : VARCHAR(255)
+ */
+CREATE PROCEDURE db_5_0.overrideName(in InternalDomainID INT UNSIGNED, in InternalEntityID INT UNSIGNED, in InternalPropertyID INT UNSIGNED, in Name VARCHAR(255))
 BEGIN
-	INSERT INTO name_overrides (domain_id, entity_id, property_id, name) VALUES (DomainID, EntityID, PropertyID, Name);
+    INSERT INTO name_overrides (domain_id, entity_id, property_id, name) VALUES (InternalDomainID, InternalEntityID, InternalPropertyID, Name);
 END;
 //
 
-CREATE PROCEDURE db_5_0.overrideDesc(in DomainID INT UNSIGNED, in EntityID INT UNSIGNED, in PropertyID INT UNSIGNED, in Description TEXT)
+/*
+ * Insert a description override.
+ *
+ * Parameters
+ * ----------
+ * InternalDomainID : INT UNSIGNED
+ *     The *internal* id of the domain.
+ * InternalEntityID : INT UNSIGNED
+ *     The *internal* id of the entity.
+ * InternalPropertyID : INT UNSIGNED
+ *     The *internal* id of the property.
+ * Description : TEXT
+ */
+CREATE PROCEDURE db_5_0.overrideDesc(in InternalDomainID INT UNSIGNED, in InternalEntityID INT UNSIGNED, in InternalPropertyID INT UNSIGNED, in Description TEXT)
 BEGIN
-	INSERT INTO desc_overrides (domain_id, entity_id, property_id, description) VALUES (DomainID, EntityID, PropertyID, Description);
+    INSERT INTO desc_overrides (domain_id, entity_id, property_id, description) VALUES (InternalDomainID, InternalEntityID, InternalPropertyID, Description);
 END;
 //
 
-CREATE PROCEDURE db_5_0.overrideType(in DomainID INT UNSIGNED, in EntityID INT UNSIGNED, in PropertyID INT UNSIGNED, in Datatype INT UNSIGNED)
+/*
+ * Insert a data type override.
+ *
+ * Parameters
+ * ----------
+ * InternalDomainID : INT UNSIGNED
+ *     The *internal* id of the domain.
+ * InternalEntityID : INT UNSIGNED
+ *     The *internal* id of the entity.
+ * InternalPropertyID : INT UNSIGNED
+ *     The *internal* id of the property.
+ * InternalDatatypeID : INT UNSIGNED
+ *     The *internal* id of the data type.
+ */
+CREATE PROCEDURE db_5_0.overrideType(in InternalDomainID INT UNSIGNED, in InternalEntityID INT UNSIGNED, in InternalPropertyID INT UNSIGNED, in InternalDataTypeID INT UNSIGNED)
 BEGIN
-	INSERT INTO data_type (domain_id, entity_id, property_id, datatype) VALUES (DomainID, EntityID, PropertyID, Datatype);
+    INSERT INTO data_type (domain_id, entity_id, property_id, datatype) VALUES (InternalDomainID, InternalEntityID, InternalPropertyID, InternalDataTypeID);
 END;
 //
 
diff --git a/procedures/query/applyIDFilter.sql b/procedures/query/applyIDFilter.sql
index b1c26b7ca63442c2d6b1b8dbc41fbb22d17f6d95..2b249471a0e70c673be1159eaffda7b0fa519ec2 100644
--- a/procedures/query/applyIDFilter.sql
+++ b/procedures/query/applyIDFilter.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.applyIDFilter;
@@ -32,71 +31,114 @@ DELIMITER //
  *
  * The `versioned` flag currently only has the effect that an `_iversion` column is also copied to
  * the target.
+ *
+ * Parameters
+ * ----------
+ * sourceSet : VARCHAR(255)
+ *     The name of the table from where we start.
+ * targetSet : VARCHAR(255)
+ *     The name of the table where we collect all the "good" ids (or NULL or same as sourceSet).
+ * o : CHAR(2)
+ *     The operator used for filtering, e.g. '=', '!=', '>', ...
+ * EntityID : VARCHAR(255)
+ *     An entity id, existing or non-existing, which we use to compare the
+ *     existing entities to using the operator.
+ * agg : CHAR(3)
+ *     An aggregate function, e.g. 'max' or 'min'. This only makes sense for number-based ids.
+ * versioned : BOOLEAN
+ *     The filter belongs to a version-aware query (e.g. FIND ANY VERSION OF
+ *     ...) and hence the sourceSet and targetSet have an `_iversion` column.
  */
 CREATE PROCEDURE db_5_0.applyIDFilter(in sourceSet VARCHAR(255), in targetSet VARCHAR(255),
-    in o CHAR(2), in vInt BIGINT, in agg CHAR(3), in versioned BOOLEAN)
+    in o CHAR(2), in EntityID VARCHAR(255), in agg CHAR(3), in versioned BOOLEAN)
 IDFILTER_LABEL: BEGIN
 DECLARE data VARCHAR(20000) DEFAULT NULL;
 DECLARE aggVal VARCHAR(255) DEFAULT NULL;
+DECLARE direction CHAR(4) DEFAULT NULL;
+DECLARE entity_id_type VARCHAR(255) DEFAULT "eids.id ";
 
 #-- get aggVal if possible
 IF agg IS NOT NULL THEN
     IF versioned THEN
         -- TODO versioned queries
         SELECT 1 FROM id_agg_with_versioning_not_implemented;
+    ELSEIF agg = "max" THEN
+        SET direction = "DESC";
+    ELSEIF agg = "min" THEN
+        SET direction = "ASC ";
+    ELSE
+        SELECT 1 FROM unknown_agg_parameter;
     END IF;
+
     SET @stmtIDAggValStr = CONCAT(
-        "SELECT ",
-        agg,
-        "(id) INTO @sAggVal FROM `",
+        "SELECT e.internal_id INTO @sAggVal FROM `",
         sourceSet,
-        "`");
+        "` AS s LEFT JOIN entity_ids AS e ON (s.id=e.internal_id) WHERE s.id>99 ORDER BY CAST(e.id AS UNSIGNED INT) ",
+        direction,
+        " LIMIT 1");
+
     PREPARE stmtIDAggVal FROM @stmtIDAggValStr;
     EXECUTE stmtIDAggVal;
     DEALLOCATE PREPARE stmtIDAggVal;
     SET aggVal = @sAggVal;
 END IF;
 
+IF o = ">" OR o = ">=" OR o = "<" or o = "<=" THEN
+    SET entity_id_type = "CAST(eids.id AS UNSIGNED INT) ";
+END IF;
+
 #-- generate stmt string
 IF targetSet IS NULL OR targetSet = sourceSet THEN
     SET data = CONCAT(
         "DELETE FROM `",
         sourceSet,
         "` WHERE ",
-        IF(o IS NULL OR vInt IS NULL,
+        IF(o IS NULL OR EntityID IS NULL,
             "1=1",
-            CONCAT("NOT id",
+            CONCAT("NOT EXISTS (SELECT 1 FROM entity_ids AS eids WHERE ",
+                entity_id_type,
                 o,
-                vInt)),
+                ' "',
+                EntityID,
+                '" ',
+                " AND eids.internal_id = `",
+                sourceSet,
+                "`.id)"
+            )),
         IF(aggVal IS NULL,
             "",
-            CONCAT(" AND id!=",
+            CONCAT(" AND `", sourceSet, "`.id!=",
                 aggVal)));
 ELSEIF versioned AND sourceSet = "entities" THEN
-
     -- ################# VERSIONING #####################
     SET data = CONCAT(
         "INSERT IGNORE INTO `",
         targetSet,
-        '` (id, _iversion) SELECT id, _get_head_iversion(id) FROM `entities` WHERE ',
-        IF(o IS NULL OR vInt IS NULL,
+        '` (id, _iversion) SELECT e.id, _get_head_iversion(e.id) FROM `entities` AS e JOIN entity_ids AS eids ON (e.id = eids.internal_id) WHERE ',
+        IF(o IS NULL OR EntityID IS NULL,
             "1=1",
-            CONCAT("id",
+            CONCAT(entity_id_type,
                 o,
-                vInt)),
+                ' "',
+                EntityID,
+                '"'
+            )),
         IF(aggVal IS NULL,
             "",
-            CONCAT(" AND id=",
+            CONCAT(" AND e.id=",
                 aggVal)),
-        ' UNION SELECT id, _iversion FROM `archive_entities` WHERE ',
-        IF(o IS NULL OR vInt IS NULL,
+        ' UNION SELECT e.id, _iversion FROM `archive_entities` AS e JOIN entity_ids AS eids ON (e.id = eids.internal_id) WHERE ',
+        IF(o IS NULL OR EntityID IS NULL,
             "1=1",
-            CONCAT("id",
+            CONCAT(entity_id_type,
                 o,
-                vInt)),
+                ' "',
+                EntityID,
+                '"'
+            )),
         IF(aggVal IS NULL,
             "",
-            CONCAT(" AND id=",
+            CONCAT(" AND e.id=",
                 aggVal)));
     -- ##################################################
 
@@ -108,12 +150,15 @@ ELSE
             '` (id, _iversion) SELECT data.id, data._iversion FROM `',
             '` (id) SELECT data.id FROM `'),
         sourceSet,
-        "` AS data WHERE ",
-        IF(o IS NULL OR vInt IS NULL,
+        "` AS data JOIN entity_ids AS eids ON (eids.internal_id = data.id) WHERE ",
+        IF(o IS NULL OR EntityID IS NULL,
             "1=1",
-            CONCAT("data.id",
+            CONCAT(entity_id_type,
                 o,
-                vInt)),
+                ' "',
+                EntityID,
+                '"'
+            )),
         IF(aggVal IS NULL,
             "",
             CONCAT(" AND data.id=",
diff --git a/procedures/query/applyPOV.sql b/procedures/query/applyPOV.sql
index 993ee9615a4e28f5351b20daf490c03c68baeac4..d1d846784a5861237ef710fe90c40f42ef9c6d11 100644
--- a/procedures/query/applyPOV.sql
+++ b/procedures/query/applyPOV.sql
@@ -1,5 +1,4 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
@@ -17,8 +16,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 /* Documentation including (?) has to be checked by an expert. */
diff --git a/procedures/query/applyTransactionFilter.sql b/procedures/query/applyTransactionFilter.sql
index 7a428b0702352677826efce0cc60bb794415102d..89b22258646740f6e8cc6138256227a168f5cbfe 100644
--- a/procedures/query/applyTransactionFilter.sql
+++ b/procedures/query/applyTransactionFilter.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,37 +18,65 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 DROP PROCEDURE IF EXISTS db_5_0.applyTransactionFilter;
 DELIMITER //
 
+
+/*
+ * Apply a transaction filter to the sourceSet and collect the remaining
+ * entities in the targetSet.
+ *
+ * Parameters
+ * ----------
+ * sourceSet : VARCHAR(255)
+ *     The name of the table from where we start.
+ * targetSet : VARCHAR(255)
+ *     The name of the table where we collect all the "good" ids (or NULL or same as sourceSet).
+ * transaction : VARCHAR(255)
+ *     The transaction's type (INSERT, UPDATE,...)
+ * operator_u : CHAR(2)
+ *     The operator used for filtering by the user, e.g. '=', '!='.
+ * realm : VARCHAR(255)
+ *     The user's realm (if filtering by the user).
+ * userName : VARCHAR(255)
+ *     The user's name (if filtering by the user).
+ * ilb : BIGINT
+ *     Inclusive Lower Bound of seconds for the transactions time.
+ * ilb_nanos : BIGINT
+ *     Inclusive Lower Bound of nanoseconds for the transactions time.
+ * eub : BIGINT
+ *     Exclusive Upper Bound of seconds for the transactions time.
+ * eub_nanos : BIGINT
+ *     Exclusive Upper Bound of nanoseconds for the transactions time.
+ * operator_t : CHAR(2)
+ *     The operator used for filtering by the transaction time, e.g. '=', '!=', '<', '>='.
+ */
 CREATE PROCEDURE db_5_0.applyTransactionFilter(in sourceSet VARCHAR(255), targetSet VARCHAR(255), in transaction VARCHAR(255), in operator_u CHAR(2), in realm VARCHAR(255), in userName VARCHAR(255), in ilb BIGINT, in ilb_nanos INT UNSIGNED, in eub BIGINT, in eub_nanos INT UNSIGNED, in operator_t CHAR(2))
 BEGIN
-	DECLARE data TEXT default CONCAT('(SELECT entity_id FROM transaction_log AS t WHERE t.transaction=\'', 
-		transaction, 
-		'\'',
-		IF(userName IS NOT NULL, 
-			CONCAT(' AND t.realm', operator_u, '? AND t.username', operator_u, '?'),
-			'' 
-		),
-		IF(ilb IS NOT NULL, 
-			CONCAT(" AND", constructDateTimeWhereClauseForColumn("t.seconds", "t.nanos", ilb, ilb_nanos, eub, eub_nanos, operator_t)),
-			""
-		),
-		')'
-	);
+    DECLARE data TEXT default CONCAT("(SELECT internal_id AS entity_id FROM transaction_log AS t JOIN entity_ids AS eids ON ( t.entity_id = eids.id ) WHERE t.transaction='",
+        transaction,
+        "'",
+        IF(userName IS NOT NULL,
+            CONCAT(' AND t.realm', operator_u, '? AND t.username', operator_u, '?'),
+            ''
+        ),
+        IF(ilb IS NOT NULL,
+            CONCAT(" AND", constructDateTimeWhereClauseForColumn("t.seconds", "t.nanos", ilb, ilb_nanos, eub, eub_nanos, operator_t)),
+            ""
+        ),
+        ')'
+    );
 
-	SET @stmtTransactionStr = makeStmt(sourceSet, targetSet, data, NULL, FALSE);
-	PREPARE stmtTransactionFilter from @stmtTransactionStr;
-	IF userName IS NOT NULL THEN
-		SET @userName = userName;
-		SET @realm = realm;
-		EXECUTE stmtTransactionFilter USING @realm, @userName;
-	ELSE
-		EXECUTE stmtTransactionFilter;
-	END IF;
+    SET @stmtTransactionStr = makeStmt(sourceSet, targetSet, data, NULL, FALSE);
+    PREPARE stmtTransactionFilter from @stmtTransactionStr;
+    IF userName IS NOT NULL THEN
+        SET @userName = userName;
+        SET @realm = realm;
+        EXECUTE stmtTransactionFilter USING @realm, @userName;
+    ELSE
+        EXECUTE stmtTransactionFilter;
+    END IF;
 
 END;
 //
diff --git a/procedures/query/initBackReference.sql b/procedures/query/initBackReference.sql
index c425dbcc6ec6c20e9b5cb2e73c0b6e1dedad1cf0..2999fb999615ffc47879dfda2a9f89e6b2b387d5 100644
--- a/procedures/query/initBackReference.sql
+++ b/procedures/query/initBackReference.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,27 +18,52 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.initBackReference;
 DELIMITER //
-CREATE PROCEDURE db_5_0.initBackReference(in pid INT UNSIGNED, in pname VARCHAR(255), in entity_id INT UNSIGNED, in ename VARCHAR(255))
+
+/*
+ * Create and initialize two new temporary tables.
+ *
+ * This is used to initialize the filterin for backreferences to a
+ * particular entity (specified by EntityID or EntityName) or using a
+ * particular property (specified by PropertyID or PropertyName).
+ *
+ * The propertiesTable contains all properties matching the PropertyID or
+ * PropertyName. The entitiesTable contains all entities matching EntityID or
+ * EntityName.
+
+ * Parameters
+ * ----------
+ * PropertyID : VARCHAR(255)
+ *     The property's (external) id.
+ * PropertyName : VARCHAR(255)
+ *     The property's name.
+ * EntityID : VARCHAR(255)
+ *     The entity's (external) id.
+ * EntityName : VARCHAR(255)
+ *     The entity's name.
+ *
+ * Select
+ * ------
+ * Tuple (propertiesTable, entitiesTable)
+ */
+CREATE PROCEDURE db_5_0.initBackReference(in PropertyID VARCHAR(255), in PropertyName VARCHAR(255), in EntityID VARCHAR(255), in EntityName VARCHAR(255))
 BEGIN
     DECLARE propertiesTable VARCHAR(255) DEFAULT NULL;
     DECLARE entitiesTable VARCHAR(255) DEFAULT NULL;
 
-    IF pname IS NOT NULL THEN
+    IF PropertyName IS NOT NULL THEN
         -- TODO versioning for properties
         call createTmpTable(propertiesTable, FALSE);
-        call initSubEntity(pid, pname, propertiesTable);
+        call initSubEntity(PropertyID, PropertyName, propertiesTable);
     END IF;
 
-    IF ename IS NOT NULL THEN
+    IF EntityName IS NOT NULL THEN
         -- TODO versioning for referencing entities
         call createTmpTable(entitiesTable, FALSE);
-        call initSubEntity(entity_id, ename, entitiesTable);
+        call initSubEntity(EntityID, EntityName, entitiesTable);
     END IF;
 
     SELECT propertiesTable, entitiesTable;
diff --git a/procedures/query/initPOV.sql b/procedures/query/initPOV.sql
index 52d6a26279c1d25cd605c3a1883db31bf6326150..31347ba9a7f2cde33e619e50e7721875232b8628 100644
--- a/procedures/query/initPOV.sql
+++ b/procedures/query/initPOV.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,15 +18,32 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 DELIMITER //
 
 
 DROP PROCEDURE IF EXISTS db_5_0.initPOVPropertiesTable//
 
-CREATE PROCEDURE db_5_0.initPOVPropertiesTable(in pid INT UNSIGNED, in pname VARCHAR(255), in sourceSet VARCHAR(255))
+/*
+ * Create and initialize a new temporary table.
+ *
+ * This is used to initialize the POV filtering. The resulting table
+ * contains all properties matching the Property component of the POV filter.
+ *
+ * Parameters
+ * ----------
+ * PropertyID : VARCHAR(255)
+ *     The property's (external) id.
+ * PropertyName : VARCHAR(255)
+ *     The property's name.
+ * sourceSet : VARCHAR(255)
+ *     The name of the table which will be filtered by the POV filter.
+ *
+ * Select
+ * ------
+ * Tuple (propertiesTable, ... and a lot of debug output)
+ */
+CREATE PROCEDURE db_5_0.initPOVPropertiesTable(in PropertyID VARCHAR(255), in PropertyName VARCHAR(255), in sourceSet VARCHAR(255))
 BEGIN
     DECLARE propertiesTable VARCHAR(255) DEFAULT NULL; /*table for property ids*/
     DECLARE replTbl VARCHAR(255) DEFAULT NULL;
@@ -38,24 +56,24 @@ BEGIN
     DECLARE t6 BIGINT DEFAULT 0;
 
 
-    IF pname is NOT NULL THEN 
+    IF PropertyName is NOT NULL THEN 
         SELECT conv( concat( substring(uid,16,3), substring(uid,10,4), substring(uid,1,8)),16,10) div 10000 - (141427 * 24 * 60 * 60 * 1000) as current_mills INTO t1 from (select uuid() uid) as alias;
         call createTmpTable2(propertiesTable);
 
-        -- fill in all properties named "pname"
+        -- fill in all properties named "PropertyName"
         SET @initPOVPropertiesTableStmt1 = CONCAT('INSERT IGNORE INTO `', propertiesTable, '` (id, id2, domain) SELECT property_id, entity_id, domain_id from name_overrides WHERE name = ? UNION ALL SELECT entity_id, domain_id, 0 FROM name_data WHERE value = ?;');
         PREPARE stmt FROM @initPOVPropertiesTableStmt1;
-        SET @pname = pname;
-        EXECUTE stmt USING @pname, @pname;
+        SET @PropertyName = PropertyName;
+        EXECUTE stmt USING @PropertyName, @PropertyName;
         SET ecount = ROW_COUNT();
 
-        -- fill in all properties with id="pid"
+        -- fill in all properties with id="PropertyID"
         SELECT conv( concat( substring(uid,16,3), substring(uid,10,4), substring(uid,1,8)),16,10) div 10000 - (141427 * 24 * 60 * 60 * 1000) as current_mills INTO t2 from (select uuid() uid) as alias;
-        IF pid IS NOT NULL THEN
+        IF PropertyID IS NOT NULL THEN
             SET @initPOVPropertiesTableStmt2 = CONCAT('INSERT IGNORE INTO `', propertiesTable, '` (id, id2, domain) VALUES (?, 0, 0)');
             PREPARE stmt FROM @initPOVPropertiesTableStmt2;
-            SET @pid = pid;
-            EXECUTE stmt USING @pid;
+            SET @PropertyID = PropertyID;
+            EXECUTE stmt USING @PropertyID;
             SET ecount = ecount + ROW_COUNT();
         END IF;
 
@@ -91,15 +109,33 @@ END //
 
 DROP PROCEDURE IF EXISTS db_5_0.initPOVRefidsTable //
 
-CREATE PROCEDURE db_5_0.initPOVRefidsTable(in vInt INT UNSIGNED, in vText VARCHAR(255))
+/*
+ * Create and initialize a new temporary table.
+ *
+ * This used to initialize the POV filtering. The resulting table
+ * contains all entities matching the Value component of the POV filter (i.e.
+ * the referenced entities).
+ *
+ * Parameters
+ * ----------
+ * PropertyID : VARCHAR(255)
+ *     The property's (external) id.
+ * PropertyName : VARCHAR(255)
+ *     The property's name.
+ *
+ * Select
+ * ------
+ * Tuple (refIdsTable)
+ */
+CREATE PROCEDURE db_5_0.initPOVRefidsTable(in PropertyID VARCHAR(255), in PropertyName VARCHAR(255))
 BEGIN
     DECLARE refIdsTable VARCHAR(255) DEFAULT NULL; /*table for referenced entity ids*/
 
     #-- for reference properties: the value is interpreted as a record type name.
-    IF vText IS NOT NULL THEN
+    IF PropertyName IS NOT NULL THEN
         -- TODO versioned queries
         call createTmpTable(refIdsTable, FALSE);
-        call initSubEntity(vInt, vText, refIdsTable);
+        call initSubEntity(PropertyID, PropertyName, refIdsTable);
         #-- now, all ids are in the refIdsTable
     END IF;
     SELECT refIdsTable;
diff --git a/procedures/query/initSubEntity.sql b/procedures/query/initSubEntity.sql
index a2f5ea67e495e4cc8cc52f0248389bc44792451f..c60ddb61df7370f52ae8218720ad69c5d2bf5023 100644
--- a/procedures/query/initSubEntity.sql
+++ b/procedures/query/initSubEntity.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
@@ -26,7 +25,22 @@ DROP PROCEDURE IF EXISTS db_5_0.initSubEntity;
 
 DELIMITER //
 
-CREATE PROCEDURE db_5_0.initSubEntity(in e_id INT UNSIGNED, in ename VARCHAR(255), in tableName VARCHAR(255))
+/*
+ * Initialize a new temporary table by loading an entity and all of its children
+ * into the table (i.e. their internal ids).
+ *
+ * This is used by initPOVRefidsTable and initBackReference for sub-property filtering.
+ *
+ * Parameters
+ * ----------
+ * EntityID : VARCHAR(255)
+ *     The entity's (external) id.
+ * EntityName : VARCHAR(255)
+ *     The entity's name.
+ * tableName : VARCHAR(255)
+ *     The table which is to be initialized.
+ */
+CREATE PROCEDURE db_5_0.initSubEntity(in EntityID VARCHAR(255), in ename VARCHAR(255), in tableName VARCHAR(255))
 BEGIN
     DECLARE ecount INT DEFAULT 0;
     DECLARE op VARCHAR(255) DEFAULT '=';
@@ -47,10 +61,11 @@ BEGIN
     SET ecount = ROW_COUNT();
     DEALLOCATE PREPARE stmt;
 
-    IF e_id IS NOT NULL THEN
-        SET @stmtStr = CONCAT('INSERT IGNORE INTO `', tableName, '` (id) VALUES (', e_id, ')');
+    IF EntityID IS NOT NULL THEN
+        SET @stmtStr = CONCAT('INSERT IGNORE INTO `', tableName, '` (id) SELECT internal_id FROM entity_ids WHERE id = ?');
         PREPARE stmt FROM @stmtStr;
-        EXECUTE stmt;
+        SET @eid = EntityID;
+        EXECUTE stmt USING @eid;
         SET ecount = ecount + ROW_COUNT();
         DEALLOCATE PREPARE stmt;
     END IF;
diff --git a/procedures/registerSubdomain.sql b/procedures/registerReplacementIds.sql
similarity index 70%
rename from procedures/registerSubdomain.sql
rename to procedures/registerReplacementIds.sql
index 4cb18e46be422e6cc65db5b33913cf06b77c18d2..2fc04ccb082ef080b7b7ae238b32cc3a7f6b415f 100644
--- a/procedures/registerSubdomain.sql
+++ b/procedures/registerReplacementIds.sql
@@ -1,9 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+ * Copyright (C) 2023 IndiScale GmbH <www.indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,33 +18,25 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
-
-
-
-
-
-
-
-
 DROP PROCEDURE IF EXISTS db_5_0.registerSubdomain;
+DROP PROCEDURE IF EXISTS db_5_0.registerReplacementIds;
 delimiter //
 
-CREATE PROCEDURE db_5_0.registerSubdomain(in amount INT UNSIGNED)
+CREATE PROCEDURE db_5_0.registerReplacementIds(in amount INT UNSIGNED)
 BEGIN
     DECLARE ED INTEGER DEFAULT NULL;
 
-    SELECT COUNT(id) INTO ED FROM entities WHERE Role='DOMAIN' AND id!=0;
+    SELECT COUNT(id) INTO ED FROM entities WHERE Role='_REPLACEMENT' AND id!=0;
 
     WHILE ED < amount DO
         INSERT INTO entities (description, role, acl) VALUES
-            (NULL, 'DOMAIN', 0);
+            (NULL, '_REPLACEMENT', 0);
+
         SET ED = ED + 1;
     END WHILE;
 
-    SELECT id as DomainID FROM entities WHERE Role='DOMAIN' and id!=0;
+    SELECT e.id as ReplacementID FROM entities AS e WHERE e.Role='_REPLACEMENT' and e.id!=0;
 
 END;
 //
diff --git a/procedures/retrieveDatatype.sql b/procedures/retrieveDatatype.sql
deleted file mode 100644
index c0ed52c30ffd506d9f0a214d2b59fd4691c4c510..0000000000000000000000000000000000000000
--- a/procedures/retrieveDatatype.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-
-
-
-
-
-
-
-DROP PROCEDURE IF EXISTS db_5_0.retrieveDatatype;
-delimiter //
-CREATE PROCEDURE db_5_0.retrieveDatatype(in DatatypeName VARCHAR(255))
-BEGIN
-
-Select e.id INTO @DatatypeID from entities e where e.name=DatatypeName AND e.role='DATATYPE' LIMIT 1;
-
-call retrieveEntity(@DatatypeID);
-
-
-
-
-END;
-//
-delimiter ;
diff --git a/procedures/retrieveEntity.sql b/procedures/retrieveEntity.sql
index 42b283d1b9c9da08761900a45f439958ec9cc075..a4264e3d44fd0b9cddbd24192b118add7bdc4e15 100644
--- a/procedures/retrieveEntity.sql
+++ b/procedures/retrieveEntity.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
@@ -36,9 +33,9 @@ drop procedure if exists db_5_0.retrieveEntity //
  *
  * Parameters
  * ----------
- * EntityID
+ * EntityID : VARCHAR(255)
  *   The entity's id.
- * Version
+ * Version : VARBINARY(255)
  *   The version id.  In this procedure only, the version may also be given as
  *   `HEAD` for the latest version or as `HEAD~n`, which retrieves the n-th
  *   ancestor of `HEAD`.
@@ -49,7 +46,7 @@ drop procedure if exists db_5_0.retrieveEntity //
  *           EntityRole, FileSize, FilePath, FileHash, ACL, Version)
  */
 create procedure db_5_0.retrieveEntity(
-    in EntityID INT UNSIGNED,
+    in EntityID VARCHAR(255),
     in Version VARBINARY(255))
 retrieveEntityBody: BEGIN
     DECLARE FilePath VARCHAR(255) DEFAULT NULL;
@@ -59,7 +56,15 @@ retrieveEntityBody: BEGIN
     DECLARE CollectionName VARCHAR(255) DEFAULT NULL;
     DECLARE IsHead BOOLEAN DEFAULT TRUE;
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
+    IF InternalEntityID IS NULL THEN
+        -- RETURN EARLY - Entity does not exist.
+        SELECT 0 FROM entities WHERE 0 = 1;
+        LEAVE retrieveEntityBody;
+    END IF;
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         -- Find out head-ness and version
@@ -73,7 +78,7 @@ retrieveEntityBody: BEGIN
         END IF;
 
         IF IsHead IS FALSE THEN
-            SET IVersion=get_iversion(EntityID, Version);
+            SET IVersion=get_iversion(InternalEntityID, Version);
 
             IF IVersion IS NULL THEN
                 -- RETURN EARLY - Version does not exist.
@@ -84,7 +89,7 @@ retrieveEntityBody: BEGIN
             SELECT path, size, HEX(hash)
                 INTO FilePath, FileSize, FileHash
                 FROM archive_files
-                WHERE file_id = EntityID
+                WHERE file_id = InternalEntityID
                 AND _iversion = IVersion
                 LIMIT 1;
 
@@ -93,7 +98,7 @@ retrieveEntityBody: BEGIN
                 FROM archive_data_type
                 WHERE domain_id = 0
                 AND entity_id = 0
-                AND property_id = EntityID
+                AND property_id = InternalEntityID
                 AND _iversion = IVersion
                 LIMIT 1;
 
@@ -102,7 +107,7 @@ retrieveEntityBody: BEGIN
                 FROM archive_collection_type
                 WHERE domain_id = 0
                 AND entity_id = 0
-                AND property_id = EntityID
+                AND property_id = InternalEntityID
                 AND _iversion = IVersion
                 LIMIT 1;
 
@@ -119,10 +124,9 @@ retrieveEntityBody: BEGIN
                 EntityID AS EntityID,
                 ( SELECT value FROM archive_name_data
                     WHERE domain_id = 0
-                    AND entity_ID = EntityID
+                    AND entity_ID = InternalEntityID
                     AND property_id = 20
                     AND _iversion = IVersion
-                    -- LIMIT 1 -- TODO Remove this line if all tests pass.
                     ) AS EntityName,
                 e.description AS EntityDesc,
                 e.role AS EntityRole,
@@ -132,7 +136,7 @@ retrieveEntityBody: BEGIN
                 (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL,
                 Version AS Version
             FROM archive_entities AS e
-            WHERE e.id = EntityID
+            WHERE e.id = InternalEntityID
             AND e._iversion = IVersion
             LIMIT 1;
 
@@ -145,33 +149,33 @@ retrieveEntityBody: BEGIN
     SELECT path, size, hex(hash)
         INTO FilePath, FileSize, FileHash
         FROM files
-        WHERE file_id = EntityID
+        WHERE file_id = InternalEntityID
         LIMIT 1;
 
-    SELECT datatype INTO DatatypeID
-        FROM data_type
-        WHERE domain_id=0
-        AND entity_id=0
-        AND property_id=EntityID
+    SELECT dt.datatype INTO DatatypeID
+        FROM data_type as dt
+        WHERE dt.domain_id=0
+        AND dt.entity_id=0
+        AND dt.property_id=InternalEntityID
         LIMIT 1;
 
     SELECT collection INTO CollectionName
         FROM collection_type
         WHERE domain_id=0
         AND entity_id=0
-        AND property_id=EntityID
+        AND property_id=InternalEntityID
         LIMIT 1;
 
     SELECT
         ( SELECT value FROM name_data
             WHERE domain_id = 0
-            AND entity_ID = DatatypeID
+            AND entity_id = DatatypeID
             AND property_id = 20 LIMIT 1 ) AS Datatype,
         CollectionName AS Collection,
         EntityID AS EntityID,
         ( SELECT value FROM name_data
             WHERE domain_id = 0
-            AND entity_ID = EntityID
+            AND entity_ID = InternalEntityID
             AND property_id = 20 LIMIT 1) AS EntityName,
         e.description AS EntityDesc,
         e.role AS EntityRole,
@@ -180,7 +184,7 @@ retrieveEntityBody: BEGIN
         FileHash AS FileHash,
         (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL,
         Version AS Version
-    FROM entities e WHERE id = EntityID LIMIT 1;
+    FROM entities e WHERE id = InternalEntityID LIMIT 1;
 END;
 //
 
diff --git a/procedures/retrieveEntityOverrides.sql b/procedures/retrieveEntityOverrides.sql
index 696447527b8c05f3b9aa57193a26c3d8fa48c874..f552a2c3b7ceafae5255ee69655af426f44b8bb7 100644
--- a/procedures/retrieveEntityOverrides.sql
+++ b/procedures/retrieveEntityOverrides.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 Indiscale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 Indiscale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,25 +18,59 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.retrieveOverrides;
 delimiter //
 
+/*
+ * Retrieve the overridden (overriding the Abstract Property's) name, description, and datatype.
+ *
+ * Parameters
+ * ----------
+ *
+ * DomainID : VARCHAR(255)
+ *     The domain id (0 or the entity'id for level-2-data)
+ * EntityID : VARCHAR(255)
+ *     The entity id (or the property'id for level-2-data)
+ * Version : VARBINARY(255)
+ *     The version of the entity. Optional
+ *
+ * ResultSet
+ * ---------
+ * collection_override, # e.g. LIST
+ * name_override,       # the name
+ * desc_override,       # the description
+ * type_override,       # the datatype, e.g. DOUBLE
+ * entity_id,           # same as input EntityID
+ * InternalPropertyID,  # internal property id, to be used when property_id
+ *                      # is NULL because a replacement is used.
+ * property_id,         # the property id
+ */
 CREATE PROCEDURE db_5_0.retrieveOverrides(
-    in DomainID INT UNSIGNED,
-    in EntityID INT UNSIGNED,
+    in DomainID VARCHAR(255),
+    in EntityID VARCHAR(255),
     in Version VARBINARY(255))
 retrieveOverridesBody: BEGIN
 
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
     DECLARE IsHead BOOLEAN DEFAULT TRUE;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalDomainID INT UNSIGNED DEFAULT 0;
+
+    -- When DomainID != 0 the EntityID could possibly be a 'replacement id'
+    -- which are internal ids by definition (and do not have external
+    -- equivalents). That's why we do the UNION here, falling back to the
+    -- EntityID.
+    SELECT temp.internal_id INTO InternalEntityID
+       FROM (SELECT internal_id AS internal_id FROM
+             entity_ids WHERE id = EntityID UNION SELECT EntityID AS internal_id) AS temp LIMIT 1;
+    -- DomainID != 0 are always normal (i.e. external) Entity ids.
+    SELECT internal_id INTO InternalDomainID from entity_ids WHERE id = DomainID;
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         IF Version IS NOT NULL THEN
-            IF DomainID = 0 THEN
+            IF InternalDomainID = 0 THEN
                 SELECT get_head_version(EntityID) = Version INTO IsHead;
             ELSE
                 SELECT get_head_version(DomainID) = Version INTO IsHead;
@@ -47,8 +80,8 @@ retrieveOverridesBody: BEGIN
         IF IsHead IS FALSE THEN
             SELECT e._iversion INTO IVersion
                 FROM entity_version as e
-                WHERE ((e.entity_id = EntityID AND DomainID = 0)
-                    OR (e.entity_id = DomainID))
+                WHERE ((e.entity_id = InternalEntityID AND InternalDomainID = 0)
+                    OR (e.entity_id = InternalDomainID))
                 AND e.version = Version;
 
             IF IVersion IS NULL THEN
@@ -62,11 +95,12 @@ retrieveOverridesBody: BEGIN
                 name AS name_override,
                 NULL AS desc_override,
                 NULL AS type_override,
-                entity_id,
-                property_id
+                EntityID AS entity_id,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
             FROM archive_name_overrides
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
@@ -77,11 +111,12 @@ retrieveOverridesBody: BEGIN
                 NULL AS name_override,
                 description AS desc_override,
                 NULL AS type_override,
-                entity_id,
-                property_id
+                EntityID AS entity_id,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
             FROM archive_desc_overrides
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
@@ -96,11 +131,12 @@ retrieveOverridesBody: BEGIN
                     AND entity_id = datatype
                     AND property_id = 20
                     LIMIT 1), datatype) AS type_override,
-                entity_id,
-                property_id
+                EntityID AS entity_id,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
             FROM archive_data_type
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
@@ -111,11 +147,12 @@ retrieveOverridesBody: BEGIN
                 NULL AS name_override,
                 NULL AS desc_override,
                 NULL AS type_override,
-                entity_id,
-                property_id
+                EntityID AS entity_id,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
             FROM archive_collection_type
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion;
 
             LEAVE retrieveOverridesBody;
@@ -127,11 +164,12 @@ retrieveOverridesBody: BEGIN
         name AS name_override,
         NULL AS desc_override,
         NULL AS type_override,
-        entity_id,
-        property_id
+        EntityID AS entity_id,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
     FROM name_overrides
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
@@ -140,11 +178,12 @@ retrieveOverridesBody: BEGIN
         NULL AS name_override,
         description AS desc_override,
         NULL AS type_override,
-        entity_id,
-        property_id
+        EntityID AS entity_id,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
     FROM desc_overrides
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
@@ -156,11 +195,12 @@ retrieveOverridesBody: BEGIN
             WHERE domain_id = 0
             AND entity_ID = datatype
             AND property_id = 20 LIMIT 1), datatype) AS type_override,
-        entity_id,
-        property_id
+        EntityID AS entity_id,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
     FROM data_type
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
@@ -169,11 +209,12 @@ retrieveOverridesBody: BEGIN
         NULL AS name_override,
         NULL AS desc_override,
         NULL AS type_override,
-        entity_id,
-        property_id
+        EntityID AS entity_id,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS property_id
     FROM collection_type
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID;
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID;
 
 
 END;
diff --git a/procedures/retrieveEntityParents.sql b/procedures/retrieveEntityParents.sql
index 12b5c287881d2c10ee591986a654d974ac1feecc..6fa29054ff15869be035515a5556beb78ab9d66c 100644
--- a/procedures/retrieveEntityParents.sql
+++ b/procedures/retrieveEntityParents.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
@@ -28,37 +25,35 @@ DROP PROCEDURE IF EXISTS db_5_0.retrieveEntityParents;
 DELIMITER //
 
 /* Retrieve the parents of an Entity.
-
-Parameters
-==========
-
-EntityID : UNSIGNED
-Child entity for which all parental relations should be deleted.
-
-Returns
-=======
-ParentID : INT UNSIGNED
-  Each parent's ID
-
-ParentName :
-  The parent's name.
-
-ParentDescription :
-  The parent's description.
-
-ParentRole :
-  The parent's Role.
-
-ACL :
-  Access control list something
+ *
+ * Parameters
+ * ----------
+ * EntityID : VARCHAR(255)
+ *     Child entity for which all parental relations should be deleted.
+ *
+ * ResultSet
+ * ---------
+ * ParentID : VARCHAR(255)
+ *   Each parent's ID
+ * ParentName : VARCHAR(255)
+ *   The parent's name.
+ * ParentDescription : TEXT
+ *   The parent's description.
+ * ParentRole : VARCHAR(255)
+ *   The parent's Role.
+ * ACL : VARBINARY(65525)
+ *   Access control list.
 */
 CREATE PROCEDURE db_5_0.retrieveEntityParents(
-    in EntityID INT UNSIGNED,
+    in EntityID VARCHAR(255),
     in Version VARBINARY(255))
 retrieveEntityParentsBody: BEGIN
 
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
     DECLARE IsHead BOOLEAN DEFAULT TRUE;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         IF Version IS NOT NULL THEN
@@ -68,7 +63,7 @@ retrieveEntityParentsBody: BEGIN
         IF IsHead IS FALSE THEN
             SELECT e._iversion INTO IVersion
                 FROM entity_version as e
-                WHERE e.entity_id = EntityID
+                WHERE e.entity_id = InternalEntityID
                 AND e.version = Version;
 
             IF IVersion IS NULL THEN
@@ -77,10 +72,10 @@ retrieveEntityParentsBody: BEGIN
             END IF;
 
             SELECT
-                i.parent AS ParentID,
+                ( SELECT id FROM entity_ids WHERE internal_id = i.parent) AS ParentID,
                 ( SELECT value FROM name_data
                     WHERE domain_id = 0
-                    AND entity_id = ParentID
+                    AND entity_id = i.parent
                     AND property_id = 20
                 ) AS ParentName, -- This is not necessarily the name of the parent at the time of
                                  -- IVersion but it is a good guess. Future implementations of the
@@ -92,7 +87,7 @@ retrieveEntityParentsBody: BEGIN
                 (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL
                 FROM archive_isa AS i JOIN entities AS e
                     ON (i.parent = e.id)
-                WHERE i.child = EntityID
+                WHERE i.child = InternalEntityID
                 AND i.child_iversion = IVersion
                 AND i.direct IS TRUE
                 ;
@@ -102,18 +97,18 @@ retrieveEntityParentsBody: BEGIN
     END IF;
 
     SELECT
-        i.parent AS ParentID,
+        ( SELECT id FROM entity_ids WHERE internal_id = i.parent) AS ParentID,
         ( SELECT value FROM name_data
             WHERE domain_id = 0
-            AND entity_id = ParentID
+            AND entity_id = i.parent
             AND property_id = 20 ) AS ParentName,
         e.description AS ParentDescription,
         e.role AS ParentRole,
         (SELECT acl FROM entity_acl AS a WHERE a.id = e.acl) AS ACL
         FROM isa_cache AS i JOIN entities AS e
             ON (i.parent = e.id)
-        WHERE i.child = EntityID
-        AND i.rpath = EntityID;
+        WHERE i.child = InternalEntityID
+        AND i.rpath = InternalEntityID;
 END
 //
 
diff --git a/procedures/retrieveEntityProperties.sql b/procedures/retrieveEntityProperties.sql
index b8bc565d73cd75cbbb3726fc93e5826725aa1c0f..024f3b0cf2dfb6a83eb41078ec30060c88693f2c 100644
--- a/procedures/retrieveEntityProperties.sql
+++ b/procedures/retrieveEntityProperties.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020-2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 
@@ -28,30 +25,67 @@ delimiter //
 
 drop procedure if exists db_5_0.retrieveEntityProperties //
 
+/*
+ * Retrieve the properties of an entity (level 1 and 2).
+ *
+ * Parameters
+ * ----------
+ *
+ * DomainID : VARCHAR(255)
+ *     The domain id (0 or the entity's id for level-2-data)
+ * EntityID : VARCHAR(255)
+ *     The entity id (or the property's id for level-2-data)
+ * Version : VARBINARY(255)
+ *     The version of the entity. Optional
+ *
+ * ResultSet
+ * ---------
+ * InternalPropertyID
+ *     Internal property id, to be used when PropertyID
+ *     is NULL because a replacement is used.
+ * PropertyID
+ *     The property id
+ * PropertyValue
+ *     The property value
+ * PropertyStatus
+ *     E.g. OBLIGATORY, FIX, ...
+ * PropertyIndex
+ *     The index of the property (for ordering).
+ * )
+ */
 create procedure db_5_0.retrieveEntityProperties(
-    in DomainID INT UNSIGNED,
-    in EntityID INT UNSIGNED,
+    in DomainID VARCHAR(255),
+    in EntityID VARCHAR(255),
     in Version VARBINARY(255))
 retrieveEntityPropertiesBody: BEGIN
 
     DECLARE IVersion INT UNSIGNED DEFAULT NULL;
     DECLARE IsHead BOOLEAN DEFAULT TRUE;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalDomainID INT UNSIGNED DEFAULT 0;
+
+    -- When DomainID != 0 the EntityID could possibly be a 'replacement id'
+    -- which are internal ids by definition (and do not have external
+    -- equivalents). That's why we do the UNION here, falling back to the
+    -- EntityID.
+    SELECT temp.internal_id INTO InternalEntityID FROM (SELECT internal_id AS internal_id FROM entity_ids WHERE id = EntityID UNION SELECT EntityID AS internal_id) AS temp LIMIT 1;
+    -- DomainID != 0 are always normal (i.e. external) Entity ids.
+    SELECT internal_id INTO InternalDomainID from entity_ids WHERE id = DomainID;
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         IF Version IS NOT NULL THEN
-            IF DomainID = 0 THEN
+            IF InternalDomainID = 0 THEN
                 SELECT get_head_version(EntityID) = Version INTO IsHead;
             ELSE
                 SELECT get_head_version(DomainID) = Version INTO IsHead;
             END IF;
-
         END IF;
 
         IF IsHead IS FALSE THEN
             SELECT e._iversion INTO IVersion
                 FROM entity_version as e
-                WHERE ((e.entity_id = EntityID AND DomainID = 0)
-                    OR (e.entity_id = DomainID))
+                WHERE ((e.entity_id = InternalEntityID AND InternalDomainID = 0)
+                    OR (e.entity_id = InternalDomainID))
                 AND e.version = Version;
 
             IF IVersion IS NULL THEN
@@ -61,121 +95,135 @@ retrieveEntityPropertiesBody: BEGIN
 
             #-- double properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 value AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_double_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- integer properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 value AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_integer_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- date properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 CONCAT(value, '.NULL.NULL') AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_date_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- datetime properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 CONCAT(value, 'UTC', IF(value_ns IS NULL, '', value_ns))
                     AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_datetime_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- text properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 value AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_text_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- enum properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 value AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_enum_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- reference properties
             SELECT
-                property_id AS PropertyID,
-                IF(value_iversion IS NULL, value,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
+                IF(value_iversion IS NULL,
+                    IF(status = "REPLACEMENT",
+                        value,
+                        ( SELECT id FROM entity_ids WHERE internal_id = value )),
                     -- make it "value@version" if necessary
-                    CONCAT(value, "@", _get_version(value, value_iversion)))
+                    CONCAT(
+                        ( SELECT id FROM entity_ids WHERE internal_id = value ),
+                          "@", _get_version(value, value_iversion)))
                     AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_reference_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- null properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 NULL AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_null_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND _iversion = IVersion
 
             UNION ALL
 
             #-- name properties
             SELECT
-                property_id AS PropertyID,
+                property_id AS InternalPropertyID,
+                ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
                 value AS PropertyValue,
                 status AS PropertyStatus,
                 pidx AS PropertyIndex
             FROM archive_name_data
-            WHERE domain_id = DomainID
-            AND entity_id = EntityID
+            WHERE domain_id = InternalDomainID
+            AND entity_id = InternalEntityID
             AND property_id != 20
             AND _iversion = IVersion;
 
@@ -185,115 +233,129 @@ retrieveEntityPropertiesBody: BEGIN
 
     #-- double properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         value AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM double_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- integer properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         value AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM integer_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- date properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         CONCAT(value, '.NULL.NULL') AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM date_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- datetime properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         CONCAT(value, 'UTC', IF(value_ns IS NULL, '', value_ns))
             AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM datetime_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- text properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         value AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM text_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- enum properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         value AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM enum_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- reference properties
     SELECT
-        property_id AS PropertyID,
-        IF(value_iversion IS NULL, value,
-            CONCAT(value, "@", _get_version(value, value_iversion)))
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
+        IF(value_iversion IS NULL,
+            IF(status = "REPLACEMENT",
+                value,
+                ( SELECT id FROM entity_ids WHERE internal_id = value )),
+            -- make it "value@version" if necessary
+            CONCAT(
+                ( SELECT id FROM entity_ids WHERE internal_id = value ),
+                  "@", _get_version(value, value_iversion)))
             AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM reference_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- null properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         NULL AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM null_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
 
     UNION ALL
 
     #-- name properties
     SELECT
-        property_id AS PropertyID,
+        property_id AS InternalPropertyID,
+        ( SELECT id FROM entity_ids WHERE internal_id = property_id ) AS PropertyID,
         value AS PropertyValue,
         status AS PropertyStatus,
         pidx AS PropertyIndex
     FROM name_data
-    WHERE domain_id = DomainID
-    AND entity_id = EntityID
+    WHERE domain_id = InternalDomainID
+    AND entity_id = InternalEntityID
     AND property_id != 20;
 
-
 END;
 //
 
diff --git a/procedures/retrieveGroup.sql b/procedures/retrieveGroup.sql
deleted file mode 100644
index 7db1b89c6e0e407e63de29682d4ef033f56b5f92..0000000000000000000000000000000000000000
--- a/procedures/retrieveGroup.sql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-
-Drop Procedure if exists db_5_0.retrieveGroup;
diff --git a/procedures/retrieveSubentity.sql b/procedures/retrieveSubentity.sql
deleted file mode 100644
index 406d668ab776451216d54ff3e2de9f4eb294872a..0000000000000000000000000000000000000000
--- a/procedures/retrieveSubentity.sql
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-DELIMITER //
-DROP PROCEDURE IF EXISTS db_5_0.retrieveSubEntity //
-/**
-CREATE PROCEDURE db_5_0.retrieveSubEntity(in EntityID INT UNSIGNED, in DomainID INT UNSIGNED)
-BEGIN
-	DECLARE FilePath VARCHAR(255) DEFAULT NULL;
-	DECLARE FileSize VARCHAR(255) DEFAULT NULL;
-	DECLARE FileHash VARCHAR(255) DEFAULT NULL;
-	
-	Select path, size, hex(hash) into FilePath, FileSize, FileHash from files where file_id = EntityID LIMIT 1;
-		Select DomainID as DomainID,
-			EntityID as EntityID, 
-			e.name as EntityName, 
-			e.description as EntityDesc, 
-			e.role as EntityRole, 
-			FileSize as FileSize, 
-			FilePath as FilePath, 
-			FileHash as FileHash 
-		from entities e where id = EntityID LIMIT 1;
-
-END;
-//
-
-**/
-DELIMITER ;
diff --git a/procedures/setFileProperties.sql b/procedures/setFileProperties.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e1efa3f4c200f37a4d1c1769ca6db1d31d27f62a
--- /dev/null
+++ b/procedures/setFileProperties.sql
@@ -0,0 +1,73 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+DROP PROCEDURE IF EXISTS setFileProperties;
+DELIMITER //
+/**
+ * Update file properties.
+ *
+ * If ENTITY_VERSIONING is enabled the old file properties are moved to
+ * `archive_files`.
+ *
+ * Parameters
+ * ----------
+ * EntityID : VARCHAR(255)
+ *   The file's id.
+ * FilePath : TEXT
+ *   Path of the file in the internal file system.  If NULL, an existing file
+ *   entity is simply deleted.
+ * FileSize : BIGINT UNSIGNED
+ *   Size of the file in bytes.
+ * FileHash : VARCHAR(255)
+ *   A Sha512 Hash of the file.
+ */
+CREATE PROCEDURE setFileProperties (
+    in EntityID VARCHAR(255),
+    in FilePath TEXT,
+    in FileSize BIGINT UNSIGNED,
+    in FileHash VARCHAR(255)
+)
+BEGIN
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+    DECLARE IVersion INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID FROM entity_ids WHERE id = EntityID;
+
+    IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
+        SELECT max(e._iversion) INTO IVersion
+            FROM entity_version AS e
+            WHERE e.entity_id = InternalEntityID;
+
+        INSERT INTO archive_files (file_id, path, size, hash,
+                _iversion)
+            SELECT file_id, path, size, hash, IVersion AS _iversion
+            FROM files
+            WHERE file_id = InternalEntityID;
+    END IF;
+
+    DELETE FROM files WHERE file_id = InternalEntityID;
+
+    IF FilePath IS NOT NULL THEN
+        INSERT INTO files (file_id, path, size, hash)
+            VALUES (InternalEntityID, FilePath, FileSize, unhex(FileHash));
+    END IF;
+
+END //
+DELIMITER ;
diff --git a/procedures/setPassword.sql b/procedures/setPassword.sql
deleted file mode 100644
index 33345d9625fadda9d1e182e7ea545e3b8fbf9e8a..0000000000000000000000000000000000000000
--- a/procedures/setPassword.sql
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-
-
-DROP PROCEDURE IF EXISTS db_5_0.setPassword;
-delimiter //
-
-CREATE PROCEDURE db_5_0.setPassword(in EntityID INT UNSIGNED, in NewPassword VARCHAR(255))
-BEGIN
-
-
-	DELETE FROM passwords where entity_id=EntityID;
-	INSERT INTO passwords (entity_id, password) VALUES (EntityID, NewPassword);
-
-END;
-//
-delimiter ;
diff --git a/procedures/updateEntity.sql b/procedures/updateEntity.sql
index f98e4795b344bbf0c4b68ac90a0848daf5e14188..3e0a53c11c2899bdea1fb9d90466ca0de0aa8cb1 100644
--- a/procedures/updateEntity.sql
+++ b/procedures/updateEntity.sql
@@ -1,11 +1,10 @@
 /*
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
  * Copyright (C) 2018 Research Group Biomedical Physics,
  * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -19,8 +18,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 DROP PROCEDURE IF EXISTS db_5_0.updateEntity;
@@ -34,7 +31,7 @@ delimiter //
  * Selects the new version identifier for the entity.
  */
 CREATE PROCEDURE db_5_0.updateEntity(
-    in EntityID INT UNSIGNED,
+    in EntityID VARCHAR(255),
     in EntityName VARCHAR(255),
     in EntityDescription TEXT,
     in EntityRole VARCHAR(255),
@@ -48,20 +45,23 @@ BEGIN
     DECLARE ParentVersion VARBINARY(255) DEFAULT NULL;
     DECLARE Transaction VARBINARY(255) DEFAULT NULL;
     DECLARE OldIVersion INT UNSIGNED DEFAULT NULL;
+    DECLARE InternalEntityID INT UNSIGNED DEFAULT NULL;
+
+    SELECT internal_id INTO InternalEntityID from entity_ids WHERE id = EntityID;
 
     call entityACL(ACLID, ACL);
 
     IF is_feature_config("ENTITY_VERSIONING", "ENABLED") THEN
         SELECT max(_iversion) INTO OldIVersion
             FROM entity_version
-            WHERE entity_id = EntityID;
+            WHERE entity_id = InternalEntityID;
 
         -- move old data to archives
         INSERT INTO archive_entities (id, description, role,
                 acl, _iversion)
             SELECT e.id, e.description, e.role, e.acl, OldIVersion
             FROM entities AS e
-            WHERE e.id = EntityID;
+            WHERE e.id = InternalEntityID;
 
         INSERT INTO archive_data_type (domain_id, entity_id, property_id,
                 datatype, _iversion)
@@ -70,7 +70,7 @@ BEGIN
             FROM data_type AS e
             WHERE e.domain_id = 0
             AND e.entity_id = 0
-            AND e.property_id = EntityID;
+            AND e.property_id = InternalEntityID;
 
         INSERT INTO archive_collection_type (domain_id, entity_id, property_id,
                 collection, _iversion)
@@ -79,16 +79,16 @@ BEGIN
             FROM collection_type as e
             WHERE e.domain_id = 0
             AND e.entity_id = 0
-            AND e.property_id = EntityID;
+            AND e.property_id = InternalEntityID;
 
 
         SET Transaction = @SRID;
         SELECT e.version INTO ParentVersion
             FROM entity_version as e
-            WHERE e.entity_id = EntityID
+            WHERE e.entity_id = InternalEntityID
             AND e._iversion = OldIVersion;
         CALL insert_single_child_version(
-            EntityID, Hash, Version,
+            InternalEntityID, Hash, Version,
             ParentVersion, Transaction);
     END IF;
 
@@ -96,34 +96,34 @@ BEGIN
         SET e.description = EntityDescription,
             e.role=EntityRole,
             e.acl = ACLID
-        WHERE e.id = EntityID;
+        WHERE e.id = InternalEntityID;
 
     -- clean up primary name, because updateEntity might be called without a
     -- prior call to deleteEntityProperties.
     DELETE FROM name_data
-        WHERE domain_id = 0 AND entity_id = EntityID AND property_id = 20;
+        WHERE domain_id = 0 AND entity_id = InternalEntityID AND property_id = 20;
     IF EntityName IS NOT NULL THEN
         INSERT INTO name_data
                 (domain_id, entity_id, property_id, value, status, pidx)
-            VALUES (0, EntityID, 20, EntityName, "FIX", 0);
+            VALUES (0, InternalEntityID, 20, EntityName, "FIX", 0);
     END IF;
 
     DELETE FROM data_type
-        WHERE domain_id=0 AND entity_id=0 AND property_id=EntityID;
+        WHERE domain_id=0 AND entity_id=0 AND property_id=InternalEntityID;
 
     DELETE FROM collection_type
-        WHERE domain_id=0 AND entity_id=0 AND property_id=EntityID;
+        WHERE domain_id=0 AND entity_id=0 AND property_id=InternalEntityID;
 
     IF Datatype IS NOT NULL THEN
         INSERT INTO data_type (domain_id, entity_id, property_id, datatype)
-            SELECT 0, 0, EntityID,
+            SELECT 0, 0, InternalEntityID,
                 ( SELECT entity_id FROM name_data WHERE domain_id = 0
                     AND property_id = 20 AND value = Datatype LIMIT 1 );
 
         IF Collection IS NOT NULL THEN
             INSERT INTO collection_type (domain_id, entity_id, property_id,
                     collection)
-                SELECT 0, 0, EntityID, Collection;
+                SELECT 0, 0, InternalEntityID, Collection;
         END IF;
     END IF;
 
diff --git a/tests/test_autotap.sql b/tests/test_autotap.sql
index ebec7304fd753261775a40a8ccfd8e765136ec0e..1ae650e346e3cd79e5396af177c6c14ffb875ea1 100644
--- a/tests/test_autotap.sql
+++ b/tests/test_autotap.sql
@@ -724,7 +724,7 @@ SELECT tap.col_collation_is('_caosdb_schema_unit_tests','entities','description'
 -- COLUMN entities.role
 
 SELECT tap.has_column('_caosdb_schema_unit_tests','entities','role','');
-SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','entities','role','enum(\'RECORDTYPE\',\'RECORD\',\'FILE\',\'DOMAIN\',\'PROPERTY\',\'DATATYPE\',\'ROLE\',\'QUERYTEMPLATE\')','');
+SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','entities','role','enum(\'RECORDTYPE\',\'RECORD\',\'FILE\',\'_REPLACEMENT\',\'PROPERTY\',\'DATATYPE\',\'ROLE\',\'QUERYTEMPLATE\')','');
 SELECT tap.col_extra_is('_caosdb_schema_unit_tests','entities','role','','');
 SELECT tap.col_default_is('_caosdb_schema_unit_tests','entities','role',NULL,'');
 SELECT tap.col_charset_is('_caosdb_schema_unit_tests','entities','role','utf8','');
@@ -1914,11 +1914,11 @@ SELECT tap.col_collation_is('_caosdb_schema_unit_tests','transaction_log','trans
 -- COLUMN transaction_log.entity_id
 
 SELECT tap.has_column('_caosdb_schema_unit_tests','transaction_log','entity_id','');
-SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','transaction_log','entity_id','int(10) unsigned','');
+SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','transaction_log','entity_id','varchar(255)','');
 SELECT tap.col_extra_is('_caosdb_schema_unit_tests','transaction_log','entity_id','','');
 SELECT tap.col_default_is('_caosdb_schema_unit_tests','transaction_log','entity_id',NULL,'');
-SELECT tap.col_charset_is('_caosdb_schema_unit_tests','transaction_log','entity_id',NULL,'');
-SELECT tap.col_collation_is('_caosdb_schema_unit_tests','transaction_log','entity_id',NULL,'');
+SELECT tap.col_charset_is('_caosdb_schema_unit_tests','transaction_log','entity_id','utf8mb4','');
+SELECT tap.col_collation_is('_caosdb_schema_unit_tests','transaction_log','entity_id','utf8mb4_bin','');
 
 -- COLUMN transaction_log.username
 
@@ -2089,11 +2089,11 @@ SELECT tap.col_collation_is('_caosdb_schema_unit_tests','user_info','status','ut
 -- COLUMN user_info.entity
 
 SELECT tap.has_column('_caosdb_schema_unit_tests','user_info','entity','');
-SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','user_info','entity','int(10) unsigned','');
+SELECT tap.col_column_type_is('_caosdb_schema_unit_tests','user_info','entity','varchar(255)','');
 SELECT tap.col_extra_is('_caosdb_schema_unit_tests','user_info','entity','','');
 SELECT tap.col_default_is('_caosdb_schema_unit_tests','user_info','entity','NULL','');
-SELECT tap.col_charset_is('_caosdb_schema_unit_tests','user_info','entity',NULL,'');
-SELECT tap.col_collation_is('_caosdb_schema_unit_tests','user_info','entity',NULL,'');
+SELECT tap.col_charset_is('_caosdb_schema_unit_tests','user_info','entity','utf8mb4','');
+SELECT tap.col_collation_is('_caosdb_schema_unit_tests','user_info','entity','utf8mb4_bin','');
 
 -- INDEXES
 SELECT tap.indexes_are('_caosdb_schema_unit_tests','user_info','`subject_entity`','');
@@ -2105,7 +2105,7 @@ SELECT tap.index_is_type('_caosdb_schema_unit_tests','user_info','subject_entity
 SELECT tap.is_indexed('_caosdb_schema_unit_tests','user_info','`entity`','');
 
 -- CONSTRAINTS
-SELECT tap.constraints_are('_caosdb_schema_unit_tests','user_info','`PRIMARY`,`subjects_ibfk_1`','');
+SELECT tap.constraints_are('_caosdb_schema_unit_tests','user_info','`PRIMARY`,`subjects_ibfk_2`','');
 
 -- CONSTRAINT user_info.PRIMARY
 
@@ -2115,10 +2115,10 @@ SELECT tap.col_is_pk('_caosdb_schema_unit_tests','user_info','`realm`,`name`',''
 
 -- CONSTRAINT user_info.subjects_ibfk_1
 
-SELECT tap.has_constraint('_caosdb_schema_unit_tests','user_info','subjects_ibfk_1','');
-SELECT tap.constraint_type_is('_caosdb_schema_unit_tests','user_info','subjects_ibfk_1','FOREIGN KEY','');
-SELECT tap.fk_on_delete('_caosdb_schema_unit_tests','user_info','subjects_ibfk_1','RESTRICT','');
-SELECT tap.fk_on_update('_caosdb_schema_unit_tests','user_info','subjects_ibfk_1','RESTRICT','');
+SELECT tap.has_constraint('_caosdb_schema_unit_tests','user_info','subjects_ibfk_2','');
+SELECT tap.constraint_type_is('_caosdb_schema_unit_tests','user_info','subjects_ibfk_2','FOREIGN KEY','');
+SELECT tap.fk_on_delete('_caosdb_schema_unit_tests','user_info','subjects_ibfk_2','RESTRICT','');
+SELECT tap.fk_on_update('_caosdb_schema_unit_tests','user_info','subjects_ibfk_2','RESTRICT','');
 
 -- ***************************************************************
 -- TABLE _caosdb_schema_unit_tests.user_roles
@@ -2509,20 +2509,6 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','getFileIdByPa
 SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','getFileIdByPath','DEFINER','');
 SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','getFileIdByPath','CONTAINS SQL','');
 
--- PROCEDURES _caosdb_schema_unit_tests.getRole
-
-SELECT tap.has_procedure('_caosdb_schema_unit_tests','getRole','');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','getRole','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','getRole','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','getRole','CONTAINS SQL','');
-
--- PROCEDURES _caosdb_schema_unit_tests.initAutoIncrement
-
-SELECT tap.has_procedure('_caosdb_schema_unit_tests','initAutoIncrement','');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','initAutoIncrement','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','initAutoIncrement','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','initAutoIncrement','CONTAINS SQL','');
-
 -- PROCEDURES _caosdb_schema_unit_tests.initBackReference
 
 SELECT tap.has_procedure('_caosdb_schema_unit_tests','initBackReference','');
@@ -2649,12 +2635,12 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','raiseWarning'
 SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','raiseWarning','DEFINER','');
 SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','raiseWarning','CONTAINS SQL','');
 
--- PROCEDURES _caosdb_schema_unit_tests.registerSubdomain
+-- PROCEDURES _caosdb_schema_unit_tests.registerReplacementIds
 
-SELECT tap.has_procedure('_caosdb_schema_unit_tests','registerSubdomain','');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','registerSubdomain','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','registerSubdomain','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','registerSubdomain','CONTAINS SQL','');
+SELECT tap.has_procedure('_caosdb_schema_unit_tests','registerReplacementIds','');
+SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','registerReplacementIds','NO','');
+SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','registerReplacementIds','DEFINER','');
+SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','registerReplacementIds','CONTAINS SQL','');
 
 -- PROCEDURES _caosdb_schema_unit_tests.initSubProperty
 
@@ -2677,13 +2663,6 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','registerTempT
 SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','registerTempTableName','DEFINER','');
 SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','registerTempTableName','CONTAINS SQL','');
 
--- PROCEDURES _caosdb_schema_unit_tests.retrieveDatatype
-
-SELECT tap.has_procedure('_caosdb_schema_unit_tests','retrieveDatatype','');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','retrieveDatatype','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','retrieveDatatype','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','retrieveDatatype','CONTAINS SQL','');
-
 -- PROCEDURES _caosdb_schema_unit_tests.retrieveEntityParents
 
 SELECT tap.has_procedure('_caosdb_schema_unit_tests','retrieveEntityParents','');
@@ -2691,13 +2670,6 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','retrieveEntit
 SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','retrieveEntityParents','DEFINER','');
 SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','retrieveEntityParents','CONTAINS SQL','');
 
--- PROCEDURES _caosdb_schema_unit_tests.setPassword
-
-SELECT tap.has_procedure('_caosdb_schema_unit_tests','setPassword','');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','setPassword','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','setPassword','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','setPassword','CONTAINS SQL','');
-
 -- PROCEDURES _caosdb_schema_unit_tests.insertIsa
 
 SELECT tap.has_procedure('_caosdb_schema_unit_tests','insertIsa','');
@@ -2754,12 +2726,5 @@ SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','insert_single
 SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','insert_single_child_version','DEFINER','');
 SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','insert_single_child_version','CONTAINS SQL','');
 
--- PROCEDURES _caosdb_schema_unit_tests.delete_all_entity_versions
-
-SELECT tap.has_procedure('_caosdb_schema_unit_tests', 'delete_all_entity_versions', '');
-SELECT tap.procedure_is_deterministic('_caosdb_schema_unit_tests','delete_all_entity_versions','NO','');
-SELECT tap.procedure_security_type_is('_caosdb_schema_unit_tests','delete_all_entity_versions','DEFINER','');
-SELECT tap.procedure_sql_data_access_is('_caosdb_schema_unit_tests','delete_all_entity_versions','CONTAINS SQL','');
-
 CALL tap.finish();
 ROLLBACK;
diff --git a/tests/test_entity_versioning.sql b/tests/test_entity_versioning.sql
index 26efd8c029e9ad01f8966ddd687ed31f3c4a2b49..f7c52a210c8baef8e781142ff645122ce95ec4fe 100644
--- a/tests/test_entity_versioning.sql
+++ b/tests/test_entity_versioning.sql
@@ -1,9 +1,8 @@
 /**
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,8 +16,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 USE _caosdb_schema_unit_tests;
@@ -34,6 +31,13 @@ CALL tap.no_plan();
 
 -- SETUP
 
+SET @EntityID1 = 10001;
+SET @EntityID2 = 10002;
+SET @EntityID3 = 10003;
+SET @EntityID4 = 10004;
+SET @EntityID5 = 10005;
+SET @EntityID6 = 10006;
+
 -- Disable versioning because we want to test `insert_single_child_version`
 -- separately from `insertEntity` but the former is called inside the latter
 -- when versioning is enabled.
@@ -46,22 +50,22 @@ INSERT INTO transactions (srid,seconds,nanos,username,realm) VALUES
 ("SRIDblieb", 3456, 4576, "you", "home");
 DELETE FROM entities WHERE id > 99;
 CALL entityACL(@ACLID1, "{acl1}");
-CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
-SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName";
+CALL insertEntity(@EntityID1, "EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
+SELECT entity_id INTO @InternalEntityID1 FROM name_data WHERE value="EntityName";
 
 
 -- TEST insert_single_child_version
 SELECT count(*) INTO @x FROM entity_version;
 SELECT tap.eq(@x, 0, "no versions there yet");
 
-CALL insert_single_child_version(@EntityID, "hashbla", "versionbla", NULL, "SRIDbla");
+CALL insert_single_child_version(@InternalEntityID1, "hashbla", "versionbla", NULL, "SRIDbla");
 SELECT _ipparent INTO @x from entity_version WHERE version="versionbla";
 SELECT tap.eq(@x, NULL, "no parent for the first version");
 
 -- add a second version
 SELECT count(*) INTO @x FROM entity_version;
 SELECT tap.eq(@x, 1, "one version there already");
-CALL insert_single_child_version(@EntityID, "hashblub", "versionblub", "versionbla", "SRIDblub");
+CALL insert_single_child_version(@InternalEntityID1, "hashblub", "versionblub", "versionbla", "SRIDblub");
 
 SELECT _ipparent INTO @x from entity_version WHERE version="versionblub";
 SELECT tap.eq(@x, 1, "the original entity is the parent");
@@ -72,7 +76,7 @@ SELECT tap.eq(@x, 2, "two versions there already");
 
 CALL tap._assert_throws(
      concat("CALL insert_single_child_version(",
-            @EntityID, ', "hashblieb", "versionblieb", "non-existing-parent", "SRIDBlieb")'),
+            @InternalEntityID1, ', "hashblieb", "versionblieb", "non-existing-parent", "SRIDBlieb")'),
      "non existing parent throws");
 
 SELECT count(*) INTO @x FROM entity_version;
@@ -80,21 +84,24 @@ SELECT tap.eq(@x, 2, "still two versions there");
 
 
 -- TEST get_primary_parent_version
-SELECT tap.eq(get_primary_parent_version(@EntityID, "versionblub"), "versionbla", "returns correct parent for versionblub");
-SELECT tap.eq(get_primary_parent_version(@EntityID, "versionbla"), NULL, "versionbla has no parent");
+SELECT tap.eq(get_primary_parent_version(@EntityID1, "versionblub"), "versionbla", "returns correct parent for versionblub");
+SELECT tap.eq(get_primary_parent_version(@EntityID1, "versionbla"), NULL, "versionbla has no parent");
 
 
+-- Reactivate when versioning's FORGET is being implemented
 -- TEST delete_all_entity_versions
 SELECT count(*) INTO @x FROM entity_version;
 SELECT tap.ok(@x > 0, "several versions in the table");
 
-CALL delete_all_entity_versions(@EntityID);
+-- CALL delete_all_entity_versions(@EntityID1);
+DELETE FROM entity_version WHERE entity_id = @InternalEntityID1;
 SELECT count(*) INTO @x FROM entity_version;
 SELECT tap.eq(@x, 0, "no versions there any more");
 
 
 -- TEARDOWN clean up
 DELETE FROM name_data WHERE entity_id > 99;
+DELETE FROM entity_ids WHERE internal_id > 99;
 DELETE FROM entities WHERE id > 99;
 
 -- #####################################################################
@@ -108,20 +115,20 @@ SELECT tap.eq(@x, 0, "before insertEntity, no versions there");
 
 -- TEST insertEntity - should produce a version w/o parent
 SET @SRID = "SRIDbla";
-CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
-SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName";
-CALL insertEntity("ParentName", "ParentDesc", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID2, "EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
+SELECT entity_id INTO @InternalEntityID2 FROM name_data WHERE value="EntityName";
+CALL insertEntity(@EntityID3, "ParentName", "ParentDesc", "RECORDTYPE", "{acl1}");
 SELECT entity_id INTO @ParentID FROM name_data WHERE value="ParentName";
-CALL insertIsa(@EntityID, @ParentID);
-CALL insertEntityProperty(0, @EntityID, 17, "null_data", NULL, NULL,
+CALL insertIsa(@EntityID2, @EntityID3);
+CALL insertEntityProperty(0, @EntityID2, 17, "null_data", NULL, NULL,
     "RECOMMENDED", NULL, "DescOverride", NULL, NULL, 0);
 
-SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @EntityID;
+SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2;
 SELECT tap.eq(@x, 1, "after insertEntity, a version is there.");
-SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @EntityID and _ipparent is NULL;
+SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2 and _ipparent is NULL;
 SELECT tap.eq(@x, 1, "after insertEntity, the _iversion number is 1.");
 
-SELECT _ipparent INTO @x from entity_version WHERE entity_id = @EntityID;
+SELECT _ipparent INTO @x from entity_version WHERE entity_id = @InternalEntityID2;
 SELECT tap.eq(@x, NULL, "no parent for the freshly inserted entity");
 SELECT tap.eq(count(*), 0, "no entity in archive_entities before first update")
     FROM archive_entities;
@@ -129,14 +136,14 @@ SELECT tap.eq(count(*), 0, "no entity in archive_entities before first update")
 
 -- TEST updateEntity - should produce a version with a parent
 SET @SRID = "SRIDblub";
-CALL deleteEntityProperties(@EntityID);
-CALL updateEntity(@EntityID, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl1}");
-SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @EntityID;
+CALL deleteEntityProperties(@EntityID2);
+CALL updateEntity(@EntityID2, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl1}");
+SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2;
 SELECT tap.eq(@x, 2, "after updateEntity, a second version is there.");
 
-SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @EntityID and _ipparent = 1;
+SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2 and _ipparent = 1;
 SELECT tap.eq(@x, 2, "after updateEntity, the _iversion number incremented.");
-SELECT _ipparent INTO @x FROM entity_version WHERE entity_id = @EntityID and _ipparent = 1;
+SELECT _ipparent INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2 and _ipparent = 1;
 SELECT tap.eq(@x, 1, "after updateEntity, the _pparent points to the first version");
 
 SELECT tap.eq(count(*), 1, "after updateEntity, one entity in archive_entities")
@@ -144,60 +151,60 @@ SELECT tap.eq(count(*), 1, "after updateEntity, one entity in archive_entities")
 
 
 -- TEST get_version_history
-CALL get_version_history(@EntityID);
+CALL get_version_history(@EntityID2);
 
 -- TEST retrieveEntity
 
 SELECT version INTO @x FROM entity_version
-    WHERE entity_id = @EntityID
+    WHERE entity_id = @InternalEntityID2
     AND _iversion = 2;
-CALL retrieveEntity(@EntityID, NULL);
-CALL retrieveEntity(@EntityID, "non-existing-version");
-CALL retrieveEntity(@EntityID, get_head_version(@EntityID));
-CALL retrieveEntity(@EntityID, @x);
+CALL retrieveEntity(@EntityID2, NULL);
+CALL retrieveEntity(@EntityID2, "non-existing-version");
+CALL retrieveEntity(@EntityID2, get_head_version(@EntityID2));
+CALL retrieveEntity(@EntityID2, @x);
 
 -- TEST retrieveEntityParents
 
-CALL retrieveEntityParents(@EntityID, NULL);
-CALL retrieveEntityParents(@EntityID, "non-existing-version");
-CALL retrieveEntityParents(@EntityID, get_head_version(@EntityID));
-CALL retrieveEntityParents(@EntityID, @x);
+CALL retrieveEntityParents(@EntityID2, NULL);
+CALL retrieveEntityParents(@EntityID2, "non-existing-version");
+CALL retrieveEntityParents(@EntityID2, get_head_version(@EntityID2));
+CALL retrieveEntityParents(@EntityID2, @x);
 
 -- TEST retrieveEntityProperties
 
-CALL retrieveEntityProperties(0, @EntityID, NULL);
-CALL retrieveEntityProperties(0, @EntityID, "non-existing-version");
-CALL retrieveEntityProperties(0, @EntityID, get_head_version(@EntityID));
-CALL retrieveEntityProperties(0, @EntityID, @x);
+CALL retrieveEntityProperties(0, @EntityID2, NULL);
+CALL retrieveEntityProperties(0, @EntityID2, "non-existing-version");
+CALL retrieveEntityProperties(0, @EntityID2, get_head_version(@EntityID2));
+CALL retrieveEntityProperties(0, @EntityID2, @x);
 
 -- TEST retrieveOverrides
 
-CALL retrieveOverrides(0, @EntityID, NULL);
-CALL retrieveOverrides(0, @EntityID, "non-existing-version");
-CALL retrieveOverrides(0, @EntityID, get_head_version(@EntityID));
-CALL retrieveOverrides(0, @EntityID, @x);
+CALL retrieveOverrides(0, @EntityID2, NULL);
+CALL retrieveOverrides(0, @EntityID2, "non-existing-version");
+CALL retrieveOverrides(0, @EntityID2, get_head_version(@EntityID2));
+CALL retrieveOverrides(0, @EntityID2, @x);
 
 
 -- and 2nd updateEntity
 SET @SRID = "SRIDblieb";
-CALL updateEntity(@EntityID, "EntityName", "EntityDesc", "RECORDTYPE", NULL, NULL, "{acl1}");
-SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @EntityID;
+CALL updateEntity(@EntityID2, "EntityName", "EntityDesc", "RECORDTYPE", NULL, NULL, "{acl1}");
+SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2;
 SELECT tap.eq(@x, 3, "after 2nd updateEntity, a 3rd version is there.");
 
-SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @EntityID and _ipparent = 2;
+SELECT _iversion INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2 and _ipparent = 2;
 SELECT tap.eq(@x, 3, "after 2nd updateEntity, the _iversion number incremented again.");
-SELECT _ipparent INTO @x FROM entity_version WHERE entity_id = @EntityID and _iversion = 3;
+SELECT _ipparent INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2 and _iversion = 3;
 SELECT tap.eq(@x, 2, "after 2nd updateEntity, the _pparent points to the 2nd version");
-SELECT tap.eq("SRIDblieb", srid, "correct transaction was stored") FROM entity_version WHERE entity_id = @EntityID AND _ipparent = 2;
+SELECT tap.eq("SRIDblieb", srid, "correct transaction was stored") FROM entity_version WHERE entity_id = @InternalEntityID2 AND _ipparent = 2;
 
 
 -- TEST deleteEntity - should remove all versions
-CALL deleteIsa(@EntityID);
-CALL deleteEntity(@EntityID);
-SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @EntityID;
+CALL deleteIsa(@EntityID3);
+CALL deleteEntity(@EntityID2);
+SELECT count(*) INTO @x FROM entity_version WHERE entity_id = @InternalEntityID2;
 SELECT tap.eq(@x, 0, "no versions there any more");
 
-CALL deleteEntity(@ParentID);
+CALL deleteEntity(@EntityID3);
 
 CALL tap.finish();
 ROLLBACK;
@@ -217,21 +224,21 @@ DELETE FROM transactions;
 -- insert entity without versioning
 DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING";
 CALL entityACL(@ACLID1, "{acl1}");
-CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID4, "EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
 SELECT count(*) INTO @NumOfEntities FROM entities;
-SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName";
+SELECT entity_id INTO @InternalEntityID4 FROM name_data WHERE value="EntityName";
 
 SET @TheUser = "TheUser"; -- used to identify the matching entry in transaction_log
 -- fill transaction_log: one entity with two updates (and one insert) and another entity with insert and delete.
 INSERT INTO transaction_log (transaction, entity_id, username, realm, seconds, nanos)
     -- the first entry is the one which is be found by _fix_unversioned
     VALUES
-        ("Update", @EntityID, @TheUser,     "CaosDB",  23458, 254),
+        ("Update", @InternalEntityID4, @TheUser,     "CaosDB",  23458, 254),
         -- the rest is dummy data
-        ("Update", @EntityID, "OtherUser",  "CaosDB",   2345, 633), -- not the latest transaction
-        ("Insert", @EntityID, "OtherUser",  "CaosDB",    245, 633), -- not the latest transaction
-        ("Insert", @EntityID + 1, @TheUser, "CaosDB",   2325, 653), -- not the right entity, inserted before our target
-        ("Delete", @EntityID + 1, @TheUser, "CaosDB", 232526, 653); -- not the right entity, deleted after our target
+        ("Update", @InternalEntityID4, "OtherUser",  "CaosDB",   2345, 633), -- not the latest transaction
+        ("Insert", @InternalEntityID4, "OtherUser",  "CaosDB",    245, 633), -- not the latest transaction
+        ("Insert", @InternalEntityID4 + 1, @TheUser, "CaosDB",   2325, 653), -- not the right entity, inserted before our target
+        ("Delete", @InternalEntityID4 + 1, @TheUser, "CaosDB", 232526, 653); -- not the right entity, deleted after our target
 
 
 SELECT tap.eq(COUNT(*), 5, "five entries in transaction_log") FROM transaction_log;
@@ -251,11 +258,11 @@ SELECT tap.eq(COUNT(*), 2,
     "after _fix_unversioned, one entry for our test entity in transactions, one for the standard entities.")
     FROM transactions;
 
-SELECT tap.eq(entity_id, @EntityID, "versioned entity has correct id") FROM entity_version WHERE entity_id > 99;
+SELECT tap.eq(entity_id, @InternalEntityID4, "versioned entity has correct id") FROM entity_version WHERE entity_id > 99;
 SELECT tap.ok(srid IS NOT NULL, "srid was generated and user/time matches entries from transaction_log")
     FROM transactions AS t JOIN transaction_log AS l
     ON (l.seconds = t.seconds AND l.nanos = t.nanos AND l.username = t.username AND l.realm = t.realm)
-    WHERE l.entity_id = @EntityID AND l.username = @TheUser;
+    WHERE l.entity_id = @InternalEntityID4444 AND l.username = @TheUser;
 
 CALL tap.finish();
 ROLLBACK;
@@ -275,18 +282,18 @@ DELETE FROM transactions;
 DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING";
 
 CALL entityACL(@ACLID1, "{acl1}");
-CALL insertEntity("EntityName1", "EntityDesc1", "RECORDTYPE", "{acl1}");
-CALL insertEntity("EntityName2", "EntityDesc2", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID5, "EntityName1", "EntityDesc1", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID6, "EntityName2", "EntityDesc2", "RECORDTYPE", "{acl1}");
 SELECT count(*) INTO @NumOfEntities FROM entities;
-SELECT entity_id INTO @EntityID1 FROM name_data WHERE value="EntityName1";
-SELECT entity_id INTO @EntityID2 FROM name_data WHERE value="EntityName2";
+SELECT entity_id INTO @InternalEntityID5 FROM name_data WHERE value="EntityName1";
+SELECT entity_id INTO @InternalEntityID6 FROM name_data WHERE value="EntityName2";
 
 INSERT INTO transaction_log (transaction, entity_id, username, realm, seconds,
         nanos)
     -- the first entry is the one which will be found by _fix_unversioned
-    VALUES ("INSERT", @EntityID1, "User", "CaosDB", 10000, 250),
-        ("INSERT", @EntityID2, "User", "CaosDB", 10000, 250),
-        ("UPDATE", @EntityID2, "User", "CaosDB", 20000, 250);
+    VALUES ("INSERT", @InternalEntityID5, "User", "CaosDB", 10000, 250),
+        ("INSERT", @InternalEntityID6, "User", "CaosDB", 10000, 250),
+        ("UPDATE", @InternalEntityID6, "User", "CaosDB", 20000, 250);
 
 
 SELECT tap.eq(COUNT(*), 3, "three entries in transaction_log") FROM transaction_log;
@@ -309,10 +316,10 @@ SELECT tap.eq(COUNT(*), 3,
 
 SELECT tap.eq(seconds, 10000, "version seconds of entity 1 is correct")
     FROM entity_version AS v JOIN transactions AS t
-    ON (v.srid = t.srid) WHERE v.entity_id = @EntityID1;
+    ON (v.srid = t.srid) WHERE v.entity_id = @InternalEntityID1;
 SELECT tap.eq(seconds, 20000, "version seconds of entity 2 is correct")
     FROM entity_version AS v JOIN transactions AS t
-    ON (v.srid = t.srid) WHERE v.entity_id = @EntityID2;
+    ON (v.srid = t.srid) WHERE v.entity_id = @InternalEntityID2;
 
 CALL tap.finish();
 ROLLBACK;
diff --git a/tests/test_insert_update_delete.sql b/tests/test_insert_update_delete.sql
index a11b05e3d9a72d6038800adebf5b73c699c2a2b8..ff1e4ec3acc6fe0121ff168279fe7659e05a914c 100644
--- a/tests/test_insert_update_delete.sql
+++ b/tests/test_insert_update_delete.sql
@@ -1,9 +1,31 @@
+/**
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
 USE _caosdb_schema_unit_tests;
 BEGIN;
 CALL tap.no_plan();
 
 -- SETUP
 
+SET @EntityID1 = 10001;
+SET @EntityID2 = 10002;
+
 -- Disable versioning and only test the non-versioning behavior
 DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING";
 
@@ -16,31 +38,31 @@ SELECT entity_id into @TextDatatypeID FROM name_data WHERE value ="TEXT";
 -- TEST insertEntity
 SELECT tap.eq(COUNT(id), 0, "No entities")
     FROM entities WHERE id>=100;
-CALL insertEntity("EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID1, "EntityName", "EntityDesc", "RECORDTYPE", "{acl1}");
 
 SELECT tap.eq(COUNT(entity_id), 1, "Entity has been inserted")
     FROM name_data WHERE value="EntityName";
 
-SELECT entity_id INTO @EntityID FROM name_data WHERE value="EntityName";
-SELECT tap.ok(@EntityID >= 100, "EntityID greater 99");
+SELECT entity_id INTO @InternalEntityID FROM name_data WHERE value="EntityName";
+SELECT tap.ok(@InternalEntityID >= 100, "EntityID greater 99");
 
 SELECT tap.eq(acl, @ACLID1, "correct acl id had been assigned")
-    FROM entities WHERE id=@EntityID;
+    FROM entities WHERE id=@InternalEntityID;
 
 
 -- TEST insertEntityProperty
-CALL insertEntity("AProperty", "APropDesc", "PROPERTY", "{acl1}");
-SELECT entity_id INTO @PropID FROM name_data WHERE value="AProperty";
-INSERT INTO data_type (domain_id, entity_id, property_id, datatype) VALUES (0, 0, @PropID, @TextDatatypeID);
+CALL insertEntity(@EntityID2, "AProperty", "APropDesc", "PROPERTY", "{acl1}");
+SELECT entity_id INTO @InternalPropertyID FROM name_data WHERE value="AProperty";
+INSERT INTO data_type (domain_id, entity_id, property_id, datatype) VALUES (0, 0, @InternalPropertyID, @TextDatatypeID);
 
 SELECT COUNT(*) INTO @x FROM null_data;
 SELECT tap.eq(@x, 0, "No data in null_data table");
-CALL insertEntityProperty(0, @EntityID, @PropID, "null_data", NULL, NULL, "RECOMMENDED", NULL, NULL, NULL, NULL, 0);
+CALL insertEntityProperty(0, @EntityID1, @EntityID2, "null_data", NULL, NULL, "RECOMMENDED", NULL, NULL, NULL, NULL, 0);
 SELECT COUNT(*) INTO @x FROM null_data;
 SELECT tap.eq(@x, 1, "One row in null_data table");
 
 -- TEST updateEntity
-CALL updateEntity(@EntityID, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl2}");
+CALL updateEntity(@EntityID1, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl2}");
 
 SELECT tap.eq(COUNT(entity_id), 0, "Old Entity name not present")
     FROM name_data WHERE value="EntityName";
@@ -48,21 +70,21 @@ SELECT tap.eq(COUNT(entity_id), 1, "Entity name has been updated")
     FROM name_data WHERE value="NewEntityName";
 
 SELECT tap.eq(acl, @ACLID2, "acl has been updated")
-    FROM entities WHERE id=@EntityID;
+    FROM entities WHERE id=@InternalEntityID;
 
 -- CALL updateEntity again an update the Name
-CALL updateEntity(@EntityID, "NewerEntityName", "NewerEntityDesc", "RECORD", NULL, NULL, "{acl2}");
-CALL updateEntity(@EntityID, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl2}");
+CALL updateEntity(@EntityID2, "NewerEntityName", "NewerEntityDesc", "RECORD", NULL, NULL, "{acl2}");
+CALL updateEntity(@EntityID2, "NewEntityName", "NewEntityDesc", "RECORD", NULL, NULL, "{acl2}");
 
 
 -- TEST deleteEntityProperties
-CALL deleteEntityProperties(@EntityID);
+CALL deleteEntityProperties(@EntityID1);
 SELECT COUNT(*) INTO @x FROM null_data;
 SELECT tap.eq(@x, 0, "data removed from null_data table");
 
 -- TEST deleteEntity
-CALL deleteEntity(@EntityID);
-CALL deleteEntity(@PropID);
+CALL deleteEntity(@EntityID1);
+CALL deleteEntity(@EntityID2);
 SELECT COUNT(id) INTO @x FROM entities WHERE id>100;
 SELECT tap.eq(@x, 0, "entity deleted");
 
diff --git a/tests/test_issues.sql b/tests/test_issues.sql
index ab64de844e01c2ad3e273d6ea1e0c24709781a09..ef5abd400387410e18057a5a2281f1d9c391a38d 100644
--- a/tests/test_issues.sql
+++ b/tests/test_issues.sql
@@ -1,9 +1,9 @@
 /**
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
  * Copyright (C) 2020 Daniel Hornung <d.hornung@indiscale.com>
+ * Copyright (C) 2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,14 +17,16 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 USE _caosdb_schema_unit_tests;
 BEGIN;
 CALL tap.no_plan();
 
+SET @EntityID1 = 10001;
+SET @EntityID2 = 10002;
+SET @EntityID3 = 10003;
+SET @EntityID4 = 10004;
 
 -- ########################################################################
 -- TEST Issues from https://gitlab.com/caosdb/caosdb-mysqlbackend/-/issues
@@ -42,23 +44,18 @@ INSERT INTO transactions (srid,seconds,nanos,username,realm) VALUES
 CALL entityACL(@ACLID1, "{acl1}");
 
 -- Insert entities and obtain IDs
-CALL insertEntity("A", "Desc A", "RECORDTYPE", "{acl1}");
-CALL insertEntity("B", "Desc B", "RECORDTYPE", "{acl1}");
-CALL insertEntity("C", "Desc C", "RECORDTYPE", "{acl1}");
-CALL insertEntity("rec", "Desc rec", "RECORD", "{acl1}");
-
-SELECT entity_id INTO @ID_A FROM name_data WHERE value="A";
-SELECT entity_id INTO @ID_B FROM name_data WHERE value="B";
-SELECT entity_id INTO @ID_C FROM name_data WHERE value="C";
-SELECT entity_id INTO @ID_rec FROM name_data WHERE value="rec";
+CALL insertEntity(@EntityID1, "A", "Desc A", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID2, "B", "Desc B", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID3, "C", "Desc C", "RECORDTYPE", "{acl1}");
+CALL insertEntity(@EntityID4, "rec", "Desc rec", "RECORD", "{acl1}");
 
 -- Insert is-a relationships
-CALL insertIsA(@ID_A, @ID_B);
-CALL insertIsA(@ID_B, @ID_C);
-CALL insertIsA(@ID_rec, @ID_A);
+CALL insertIsA(@EntityID1, @EntityID2);
+CALL insertIsA(@EntityID2, @EntityID3);
+CALL insertIsA(@EntityID4, @EntityID1);
 
 -- Try to delete last child
 -- leads to failure in issue #21
-CALL deleteIsa(@ID_rec);
+CALL deleteIsa(@EntityID4);
 
 ROLLBACK;
diff --git a/tests/test_reference_values.sql b/tests/test_reference_values.sql
index 47b4db4d33cd7e841da610aca886a3d6bd4947d3..2b9dcefc8f6244f1753185fe86e351c847baa3a2 100644
--- a/tests/test_reference_values.sql
+++ b/tests/test_reference_values.sql
@@ -1,9 +1,8 @@
 /**
- * ** header v3.0
  * This file is a part of the CaosDB Project.
  *
- * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
- * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2020,2023 IndiScale GmbH <info@indiscale.com>
+ * Copyright (C) 2020,2023 Timm Fitschen <t.fitschen@indiscale.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
@@ -17,8 +16,6 @@
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
  */
 
 USE _caosdb_schema_unit_tests;
@@ -37,9 +34,14 @@ INSERT INTO transactions (srid,seconds,nanos,username,realm) VALUES
 ("SRIDbla", 1234, 2345, "me", "home"),
 ("SRIDblub", 2345, 3465, "me", "home"),
 ("SRIDblieb", 3456, 4576, "you", "home");
-SET @EntityID=99;
+SET @EntityID="99";
 SET @PropertyID=11;
 SET @Value=50;
+SET @SRID="SRIDbla";
+call insertEntity(@EntityID, "TheName", "TheDesc", "RecordType", "{}");
+call insertEntity(@Value, "RefValue", "ValueDesc", "Record", "{}");
+SELECT internal_id INTO @InternalEntityID FROM entity_ids WHERE id = @EntityID;
+SELECT internal_id INTO @InternalValueID FROM entity_ids WHERE id = @Value;
 
 -- switch off versioning
 DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING";
@@ -49,16 +51,16 @@ CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
     NULL, "FIX", NULL, NULL, NULL, NULL, 0);
 
 -- TODO switch expected/actual
-SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
-SELECT tap.eq(99, entity_id, "entity ok") FROM reference_data;
-SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
-SELECT tap.eq(50, value, "value ok") FROM reference_data;
+SELECT tap.eq("0", domain_id, "domain ok") FROM reference_data;
+SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
+SELECT tap.eq("11", property_id, "property ok") FROM reference_data;
+SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
 SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
 SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
-SELECT tap.eq(NULL, value_iversion, "value_iversion ok") FROM reference_data;
+SELECT tap.eq(NULL, value_iversion, "value_iversion ok 1") FROM reference_data;
 
 -- clean up
-DELETE FROM reference_data WHERE domain_id=0 AND entity_id=99;
+DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalValueID;
 
 -- #####################################################################
 -- TODO TEST insertEntityProperty with Versioning
@@ -69,39 +71,43 @@ INSERT INTO feature_config (_key, _value) VALUES ("ENTITY_VERSIONING", "ENABLED"
 
 
 -- TEST insertEntityProperty with Versioning - REFERENCE HEAD
-SET @VALUE="50";
 CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
     NULL, "FIX", NULL, NULL, NULL, NULL, 0);
 
 -- TODO switch expected/actual
 SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
-SELECT tap.eq(99, entity_id, "entity ok") FROM reference_data;
+SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
 SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
-SELECT tap.eq(50, value, "value ok") FROM reference_data;
+SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
 SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
 SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
-SELECT tap.eq(value_iversion, NULL, "value_iversion ok") FROM reference_data;
+SELECT tap.eq(value_iversion, NULL, "value_iversion ok 2") FROM reference_data;
 
-DELETE FROM reference_data WHERE domain_id=0 AND entity_id=99;
+DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalEntityID;
 
 
 -- TEST insertEntityProperty with Versioning - Reference version
-CALL insert_single_child_version(50, "hashbla", "versionbla", NULL, "SRIDbla");
-CALL insert_single_child_version(50, "hashblub", "versionblub", "versionbla", "SRIDblub");
-
-SET @VALUE="50@versionbla";
+SELECT * FROM entity_ids;
+SELECT * FROM entity_version;
+SELECT e.version INTO @ParentVersion
+    FROM entity_version as e
+    WHERE e.entity_id = @InternalValueID
+    AND e._iversion = 1;
+CALL insert_single_child_version(@InternalValueID, "hashblub", "versionblub", @ParentVersion, "SRIDblub");
+
+SET @VALUE=CONCAT("50@", @ParentVersion);
 CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
     NULL, "FIX", NULL, NULL, NULL, NULL, 0);
 
 SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
-SELECT tap.eq(99, entity_id, "entity ok") FROM reference_data;
+SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
 SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
-SELECT tap.eq(50, value, "value ok") FROM reference_data;
+SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
 SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
 SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
-SELECT tap.eq(value_iversion, "1", "value_iversion ok") FROM reference_data;
+SELECT tap.eq(value_iversion, "1", "value_iversion ok 3") FROM reference_data;
 
-DELETE FROM reference_data WHERE domain_id=0 AND entity_id=99;
+DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalEntityID;
 
 SET @VALUE="50@versionblub";
 CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
@@ -109,12 +115,12 @@ CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
 
 -- TODO switch expected/actual
 SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
-SELECT tap.eq(99, entity_id, "entity ok") FROM reference_data;
+SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
 SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
-SELECT tap.eq(50, value, "value ok") FROM reference_data;
+SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
 SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
 SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
-SELECT tap.eq(value_iversion, "2", "value_iversion ok") FROM reference_data;
+SELECT tap.eq(value_iversion, "2", "value_iversion ok 4") FROM reference_data;
 
 
 -- invalid values throw errors