diff --git a/dbrepo-metadata-db/setup-schema.sql b/dbrepo-metadata-db/setup-schema.sql
index a24971600a29e3ab0371454f759b16ad99807adf..e207d09e4452cd2c5451550f93daedf5f2e48f5d 100644
--- a/dbrepo-metadata-db/setup-schema.sql
+++ b/dbrepo-metadata-db/setup-schema.sql
@@ -304,7 +304,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_concepts`
     id      bigint    NOT NULL,
     cID     bigint    NOT NULL,
     created timestamp NOT NULL DEFAULT NOW(),
-    PRIMARY KEY (id),
+    PRIMARY KEY (id, cid),
     FOREIGN KEY (cID) REFERENCES mdb_columns (ID)
 ) WITH SYSTEM VERSIONING;
 
@@ -313,7 +313,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_units`
     id      bigint    NOT NULL,
     cID     bigint    NOT NULL,
     created timestamp NOT NULL DEFAULT NOW(),
-    PRIMARY KEY (id),
+    PRIMARY KEY (id, cID),
     FOREIGN KEY (cID) REFERENCES mdb_columns (ID)
 ) WITH SYSTEM VERSIONING;
 
diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
index 6a0ecd6de983cf09722372e7ba2d369c35edfeea..8c4dd227c1dbfd5643eb07cdb08468bcbe56fbb5 100644
--- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
+++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
@@ -88,13 +88,13 @@ public class TableColumn implements Comparable<TableColumn> {
     @CreatedDate
     private Instant created;
 
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
     @JoinTable(name = "mdb_columns_concepts",
             joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false),
             inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id"))
     private TableColumnConcept concept;
 
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
     @JoinTable(name = "mdb_columns_units",
             joinColumns = @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false),
             inverseJoinColumns = @JoinColumn(name = "id", referencedColumnName = "id"))
diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java
index ca9853256d9b36dd772a23b8e38288df5da369ff..5d6edc84d85f2d5ebda0b370a73ad6345ac27029 100644
--- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java
+++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java
@@ -47,7 +47,7 @@ public class TableColumnConcept {
     private Instant created;
 
     @ToString.Exclude
-    @OneToMany(fetch = FetchType.LAZY)
+    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE})
     @org.springframework.data.annotation.Transient
     @JoinTable(name = "mdb_columns_concepts",
             inverseJoinColumns = {
diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java
index 8f115bdf13fe12f7aff76e6eb1d6a09658d5eccf..01cb3a0faac85b1b7e0eb899f52bd62fd90cc863 100644
--- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java
+++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java
@@ -47,9 +47,9 @@ public class TableColumnUnit {
     private Instant created;
 
     @ToString.Exclude
-    @OneToMany(fetch = FetchType.LAZY)
+    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE})
     @org.springframework.data.annotation.Transient
-    @JoinTable(name = "mdb_columns_concepts",
+    @JoinTable(name = "mdb_columns_units",
             inverseJoinColumns = {
                     @JoinColumn(name = "cid", referencedColumnName = "id", insertable = false, updatable = false)
             },
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
index ebe9b7375d672f0d57fcae8e6927f5bdb74a23da..4b515952b62b2193d9ffbcf22fb4fe95dce72f56 100644
--- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
@@ -87,7 +87,7 @@ public class TableColumnEndpoint {
             throws TableNotFoundException, TableMalformedException, DatabaseNotFoundException,
             ContainerNotFoundException, NotAllowedException, SemanticEntityPersistException,
             SemanticEntityNotFoundException, QueryMalformedException, AccessDeniedException {
-        log.debug("endpoint update table, id={}, tableId={}, {}", id, tableId, PrincipalUtil.formatForDebug(principal));
+        log.debug("endpoint update table, id={}, tableId={}, columnId={}, {}", id, tableId, columnId, PrincipalUtil.formatForDebug(principal));
         if (principal != null && !UserUtil.hasRole(principal, "modify-foreign-table-column-semantics")) {
             endpointValidator.validateOnlyAccess(id, principal, true);
             endpointValidator.validateOnlyOwnerOrWriteAll(id, tableId, principal);
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
index 3841509198c3d4aa4590d635a0bf7281d8d8e238..4e0887db8edc163a559da3e846c32a5add965035 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
@@ -125,13 +125,13 @@ public class SemanticServiceImpl implements SemanticService {
                     .build();
         }
         /* save in metadata database */
-        final TableColumnConcept concept = tableMapper.entityDtoToTableColumnConcept(
-                entityService.findOneByUri(ontology, uri));
-        log.info("Saved concept with uri {} in metadata database", concept.getUri());
+        final TableColumnConcept concept = tableMapper.entityDtoToTableColumnConcept(entityService.findOneByUri(ontology, uri));
+        final TableColumnConcept entity = tableColumnConceptRepository.save(concept);
+        log.info("Saved concept with uri {} in metadata database", entity.getUri());
         /* save in open search database */
-        conceptIdxRepository.save(tableMapper.tableColumnConceptToConceptDto(concept));
-        log.info("Saved concept with uri {} in open search database", concept.getUri());
-        return concept;
+        conceptIdxRepository.save(tableMapper.tableColumnConceptToConceptDto(entity));
+        log.info("Saved concept with uri {} in open search database", entity.getUri());
+        return entity;
     }
 
     @Override
@@ -144,11 +144,12 @@ public class SemanticServiceImpl implements SemanticService {
         }
         /* save in metadata database */
         final TableColumnUnit unit = tableMapper.entityDtoToTableColumnUnit(entityService.findOneByUri(ontology, uri));
-        log.info("Saved unit with uri {} in metadata database", unit.getUri());
+        final TableColumnUnit entity = tableColumnUnitRepository.save(unit);
+        log.info("Saved unit with uri {} in metadata database", entity.getUri());
         /* save in open search database */
-        unitIdxRepository.save(tableMapper.tableColumnUnitToUnitDto(unit));
-        log.info("Saved unit with uri {} in open search database", unit.getUri());
-        return unit;
+        unitIdxRepository.save(tableMapper.tableColumnUnitToUnitDto(entity));
+        log.info("Saved unit with uri {} in open search database", entity.getUri());
+        return entity;
     }
 
     private Ontology getCompatibleOntology(String uri) {
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
index fa5e9d60f43bd61e3cbd915e097d7dcad7d5bb35..8330501cb2db3edc236527e3f2117bba05537fb0 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
@@ -246,24 +246,26 @@ public class TableServiceImpl extends HibernateConnector implements TableService
         if (updateDto.getUnitUri() != null) {
             try {
                 column.setUnit(semanticService.findUnit(updateDto.getUnitUri()));
+                log.debug("Found unit with uri {} in metadata database", updateDto.getUnitUri());
             } catch (UnitNotFoundException e) {
-                log.warn("Unit with uri {} not found in metadata database", updateDto.getUnitUri());
                 column.setUnit(semanticService.saveUnit(updateDto.getUnitUri()));
+                log.info("Unit with uri {} was created in metadata database", updateDto.getUnitUri());
             }
         } else {
             column.setUnit(null);
-            log.debug("remove unit of column, column={}", column);
+            log.debug("remove unit of column with id={}", columnId);
         }
         if (updateDto.getConceptUri() != null) {
             try {
                 column.setConcept(semanticService.findConcept(updateDto.getConceptUri()));
+                log.debug("Found concept with uri {} in metadata database", updateDto.getConceptUri());
             } catch (ConceptNotFoundException e) {
-                log.warn("Concept with uri {} not found in metadata database", updateDto.getConceptUri());
                 column.setConcept(semanticService.saveConcept(updateDto.getConceptUri()));
+                log.info("Concept with uri {} was created in metadata database", updateDto.getConceptUri());
             }
         } else {
             column.setConcept(null);
-            log.debug("remove ColumnConcept of column, column={}", column);
+            log.debug("remove ColumnConcept of column with id={}", columnId);
         }
         /* update in metadata database */
         final TableColumn out = tableColumnRepository.save(column);
diff --git a/dbrepo-search-service/app/api/routes.py b/dbrepo-search-service/app/api/routes.py
index be2812da9d0cb71fef278433c88635005611418b..b6d45b3091867b94f40f6118cf7a048b909a695d 100644
--- a/dbrepo-search-service/app/api/routes.py
+++ b/dbrepo-search-service/app/api/routes.py
@@ -154,8 +154,6 @@ def search():
     search_term = req_body.get("search_term")
     t1 = req_body.get("t1")
     t2 = req_body.get("t2")
-    field = req_body.get("field")
-    value = req_body.get("value")
     fieldValuePairs = req_body.get("field_value_pairs")
     response = general_search(search_term, t1, t2, fieldValuePairs)
     return response, 200
diff --git a/dbrepo-search-service/app/opensearch_client.py b/dbrepo-search-service/app/opensearch_client.py
index 2dcc1e0f7c4b8beae08a799c8e9dc1dd7f83e64e..0b454b05d0b26a8d44c61253f607aa3a68ecbf7b 100644
--- a/dbrepo-search-service/app/opensearch_client.py
+++ b/dbrepo-search-service/app/opensearch_client.py
@@ -173,8 +173,19 @@ def general_search(search_term=None, t1=None, t2=None, fieldValuePairs=None):
         )
         response["status"] = 200
         return response
-    if t1 and t2 is not None:
-        logging.debug('query has time range present')
+    if t1 is not None:
+        logging.debug(f"query has start value {t1} present")
+        time_range_query = {
+            "range": {
+                "created": {
+                    "gte": t1,
+                    "lte": t2,
+                }
+            }
+        }
+        queries.append(time_range_query)
+    if t1 is not None and t2 is not None:
+        logging.debug(f"query has start value {t1} and end value {t2} present")
         time_range_query = {
             "range": {
                 "created": {
diff --git a/dbrepo-ui/api/database.service.js b/dbrepo-ui/api/database.service.js
index 7eb8f36f074b8d2197172665bd92df323f9dfe2c..fa020ef185a8f1e18a5d814ff8af9157240e0834 100644
--- a/dbrepo-ui/api/database.service.js
+++ b/dbrepo-ui/api/database.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class DatabaseService {
   findAll () {
@@ -11,9 +10,7 @@ class DatabaseService {
           resolve(databases)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load databases', error)
-          Vue.$toast.error(`[${code}] Failed to load databases: ${message}`)
+          displayError(error, 'Failed to load databases')
           reject(error)
         })
     })
@@ -28,9 +25,7 @@ class DatabaseService {
           resolve(databases)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load my databases', error)
-          Vue.$toast.error(`[${code}] Failed to load my databases: ${message}`)
+          displayError(error, 'Failed to load my databases')
           reject(error)
         })
     })
@@ -45,9 +40,7 @@ class DatabaseService {
           resolve(count)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to count databases', error)
-          Vue.$toast.error(`[${code}] Failed to count databases: ${message}`)
+          displayError(error, 'Failed to count databases')
           reject(error)
         })
     })
@@ -61,9 +54,7 @@ class DatabaseService {
           console.debug('response database', database)
           resolve(database)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load database', error)
-          Vue.$toast.error(`[${code}] Failed to load database: ${message}`)
+          displayError(error, 'Failed to load database')
           reject(error)
         })
     })
@@ -77,9 +68,7 @@ class DatabaseService {
           console.debug('response database', database)
           resolve(database)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to create database', error)
-          Vue.$toast.error(`[${code}] Failed to create database: ${message}`)
+          displayError(error, 'Failed to create database')
           reject(error)
         })
     })
@@ -90,9 +79,7 @@ class DatabaseService {
       api.delete(`/api/database/${databaseId}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to delete database', error)
-          Vue.$toast.error(`[${code}] Failed to delete database: ${message}`)
+          displayError(error, 'Failed to delete database')
           reject(error)
         })
     })
@@ -106,9 +93,7 @@ class DatabaseService {
           console.debug('response database', database)
           resolve(database)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to modify database visibility', error)
-          Vue.$toast.error(`[${code}] Failed to modify database visibility: ${message}`)
+          displayError(error, 'Failed to modify database visibility')
           reject(error)
         })
     })
@@ -122,9 +107,7 @@ class DatabaseService {
           console.debug('response database', database)
           resolve(database)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to modify database owner', error)
-          Vue.$toast.error(`[${code}] Failed to modify database owner: ${message}`)
+          displayError(error, 'Failed to modify database owner')
           reject(error)
         })
     })
@@ -140,10 +123,8 @@ class DatabaseService {
         })
         .catch((error) => {
           const { status } = error
-          const { code, message } = error.response.data
           if (status !== 401 && status !== 403 && status !== 405) { /* ignore no access errors */
-            console.error('Failed to check database access', error)
-            Vue.$toast.error(`[${code}] Failed to check database access: ${message}`)
+            displayError(error, 'Failed to check database access')
             reject(error)
           }
         })
@@ -159,9 +140,7 @@ class DatabaseService {
           resolve(database)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to modify database access', error)
-          Vue.$toast.error(`[${code}] Failed to modify database access: ${message}`)
+          displayError(error, 'Failed to modify database access')
           reject(error)
         })
     })
@@ -172,9 +151,7 @@ class DatabaseService {
       api.delete(`/api/database/${databaseId}/access/${userId}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to revoke database access', error)
-          Vue.$toast.error(`[${code}] Failed to revoke database access: ${message}`)
+          displayError(error, 'Failed to revoke database access')
           reject(error)
         })
     })
@@ -185,9 +162,7 @@ class DatabaseService {
       api.post(`/api/database/${databaseId}/access/${userId}`, { type }, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to give database access', error)
-          Vue.$toast.error(`[${code}] Failed to give database access: ${message}`)
+          displayError(error, 'Failed to give database access')
           reject(error)
         })
     })
@@ -202,9 +177,7 @@ class DatabaseService {
           resolve(licenses)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load licenses', error)
-          Vue.$toast.error(`[${code}] Failed to load licenses: ${message}`)
+          displayError(error, 'Failed to load licenses')
           reject(error)
         })
     })
@@ -219,9 +192,7 @@ class DatabaseService {
           resolve(view)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to find view', error)
-          Vue.$toast.error(`[${code}] Failed to find view: ${message}`)
+          displayError(error, 'Failed to find view')
           reject(error)
         })
     })
@@ -236,9 +207,7 @@ class DatabaseService {
           resolve(view)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to delete view', error)
-          Vue.$toast.error(`[${code}] Failed to delete view: ${message}`)
+          displayError(error, 'Failed to create view')
           reject(error)
         })
     })
@@ -249,9 +218,7 @@ class DatabaseService {
       api.delete(`/api/database/${databaseId}/view/${viewId}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to delete view', error)
-          Vue.$toast.error(`[${code}] Failed to delete view: ${message}`)
+          displayError(error, 'Failed to delete view')
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/index.js b/dbrepo-ui/api/index.js
index ed74b41a8085364ff600214cba82c5ff62bc8efb..c56e45b3ddd33a95128133fb6966ec9dbd6ca6e6 100644
--- a/dbrepo-ui/api/index.js
+++ b/dbrepo-ui/api/index.js
@@ -13,8 +13,13 @@ const instance = axios.create({
 
 function displayError (error, warning) {
   const { code, message } = error.response.data
+  if (code && message) {
+    console.error(warning, error)
+    Vue.$toast.error(`[${code}] ${warning}: ${message}`)
+    return
+  }
   console.error(warning, error)
-  Vue.$toast.error(`[${code}] ${warning}: ${message}`)
+  Vue.$toast.error(`[${error.code}] ${warning}: ${error.message}`)
 }
 
 export default instance
diff --git a/dbrepo-ui/api/search.service.js b/dbrepo-ui/api/search.service.js
index 2dac62689fa3fe5cc329af3ddeeb1942fbfa5068..faca4dd92a5576350c8d88e692d3e3a8c2b92202 100644
--- a/dbrepo-ui/api/search.service.js
+++ b/dbrepo-ui/api/search.service.js
@@ -23,8 +23,12 @@ class SearchService {
     // transform values to what the search API expects
     const searchTerm = searchData.search_term
     delete searchData.search_term
+    const t1 = searchData.t1
+    const t2 = searchData.t2
     searchData = Object.fromEntries(Object.entries(searchData).filter(([_, v]) => v != null && v !== '')) // https://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript
     const payload = {
+      t1,
+      t2,
       search_term: searchTerm,
       field_value_pairs: { ...searchData }
     }
diff --git a/dbrepo-ui/api/semantic.mapper.js b/dbrepo-ui/api/semantic.mapper.js
new file mode 100644
index 0000000000000000000000000000000000000000..79f71083bd4d4807c2f983bba2a85da9c6f07567
--- /dev/null
+++ b/dbrepo-ui/api/semantic.mapper.js
@@ -0,0 +1,17 @@
+class SemanticMapper {
+  mapConcepts (concepts) {
+    return concepts.map((concept) => {
+      concept.name = concept.name ? concept.name : concept.uri
+      return concept
+    })
+  }
+
+  mapUnits (units) {
+    return units.map((unit) => {
+      unit.name = unit.name ? unit.name : unit.uri
+      return unit
+    })
+  }
+}
+
+export default new SemanticMapper()
diff --git a/dbrepo-ui/api/user.service.js b/dbrepo-ui/api/user.service.js
index 0eacd13861c1c9ef74b10cb74c4a91ba554b2aaf..fd4cc2ba8b8112a16d50cc1934af2adebf1c4c3d 100644
--- a/dbrepo-ui/api/user.service.js
+++ b/dbrepo-ui/api/user.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 import UserMapper from '@/api/user.mapper'
 
 class UserService {
@@ -12,9 +11,7 @@ class UserService {
           resolve(users)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load users', error)
-          Vue.$toast.error(`[${code}] Failed to load users: ${message}`)
+          displayError(error, 'Failed to load users')
           reject(error)
         })
     })
@@ -28,9 +25,7 @@ class UserService {
           console.debug('response user', response.data, 'mapped user', user)
           resolve(user)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load user', error)
-          Vue.$toast.error(`[${code}] Failed to load user: ${message}`)
+          displayError(error, 'Failed to load user')
           reject(error)
         })
     })
@@ -44,9 +39,7 @@ class UserService {
           console.debug('response user', response.data, 'mapped user', user)
           resolve(user)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to update user information', error)
-          Vue.$toast.error(`[${code}] Failed to update user information: ${message}`)
+          displayError(error, 'Failed to update user information')
           reject(error)
         })
     })
@@ -61,17 +54,15 @@ class UserService {
           resolve(user)
         }).catch((error) => {
           const { status } = error
-          const { code, message } = error.response.data
           if (status === 417) {
-            Vue.$toast.error('This e-mail address is already taken')
+            displayError(error, 'This e-mail address is already taken')
           } else if (status === 409) {
-            Vue.$toast.error('This username is already taken')
+            displayError(error, 'This username is already taken')
           } else if (status === 428) {
-            Vue.$toast.warning(`[${code}] Account was created: ${message}`)
+            displayError(error, 'Account was created')
           } else {
-            Vue.$toast.error(`[${code}] Failed to create user: ${message}`)
+            displayError(error, 'Failed to create user')
           }
-          console.error('Failed to create user', error)
           this.loading = false
           reject(error)
         })
@@ -83,9 +74,7 @@ class UserService {
       api.put(`/api/user/${id}/password`, { password }, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to update user password', error)
-          Vue.$toast.error(`[${code}] Failed to update user password: ${message}`)
+          displayError(error, 'Failed to update password')
           reject(error)
         })
     })
@@ -96,9 +85,7 @@ class UserService {
       api.put(`/api/user/${id}/theme`, { theme_dark: themeDark }, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to update user theme', error)
-          Vue.$toast.error(`[${code}] Failed to update user theme: ${message}`)
+          displayError(error, 'Failed to update theme')
           reject(error)
         })
     })
diff --git a/dbrepo-ui/components/search/AdvancedSearch.vue b/dbrepo-ui/components/search/AdvancedSearch.vue
index ff71d33cd36e25837d2cd5bc286039d4e52ec478..3ed3e3cddcd8b48a9548a22f423d735c1661e13e 100644
--- a/dbrepo-ui/components/search/AdvancedSearch.vue
+++ b/dbrepo-ui/components/search/AdvancedSearch.vue
@@ -13,6 +13,7 @@
               label="Type" />
           </v-col>
         </v-row>
+        <p>The following fields are <code>AND</code> connected and depend on the type above.</p>
         <v-row dense>
           <v-col cols="3">
             <v-text-field
@@ -69,6 +70,44 @@
               clearable />
           </v-col>
         </v-row>
+        <p v-if="isColumnFilter" class="mt-4">
+          If you select a <code>concept</code> and <code>unit</code>, you can search across columns regardless of their
+          unit of measurement.
+        </p>
+        <v-row v-if="isColumnFilter" dense>
+          <v-col cols="3">
+            <v-select
+              v-model="advancedSearchData['concept.uri']"
+              clearable
+              :items="concepts"
+              item-text="name"
+              item-value="uri"
+              label="Concept" />
+          </v-col>
+          <v-col cols="3">
+            <v-select
+              v-model="advancedSearchData['unit.uri']"
+              clearable
+              :items="units"
+              item-text="name"
+              item-value="uri"
+              label="Unit" />
+          </v-col>
+          <v-col cols="3">
+            <v-text-field
+              v-model="advancedSearchData['t1']"
+              clearable
+              type="number"
+              label="Start Value" />
+          </v-col>
+          <v-col cols="3">
+            <v-text-field
+              v-model="advancedSearchData['t2']"
+              clearable
+              type="number"
+              label="End Value" />
+          </v-col>
+        </v-row>
         <v-row dense>
           <v-btn class="mr-2" color="primary" :loading="loading" small @click="advancedSearch">
             Search
@@ -81,6 +120,8 @@
 <script>
 import SearchService from '@/api/search.service'
 import QueryMapper from '@/api/query.mapper'
+import SemanticService from '@/api/semantic.service'
+import SemanticMapper from '@/api/semantic.mapper'
 
 export default {
   data () {
@@ -88,6 +129,8 @@ export default {
       loading: false,
       loadingFields: false,
       showAdvancedSearch: false,
+      concepts: [],
+      units: [],
       columnTypes: QueryMapper.mySql8DataTypes().map((datatype) => {
         datatype.value = datatype.value.toUpperCase()
         return datatype
@@ -123,6 +166,9 @@ export default {
         hideNameField: selectedOption === 'identifier',
         hideInternalNameField: ['identifier', 'user', 'concept', 'unit'].includes(selectedOption)
       }
+    },
+    isColumnFilter () {
+      return this.advancedSearchData.type === 'column'
     }
   },
   watch: {
@@ -131,7 +177,6 @@ export default {
         if (!newType) {
           return
         }
-        console.debug('switched advanced search type to', newType)
         this.resetAdvancedSearchFields()
         this.loadingFields = true
         SearchService.getFields(newType)
@@ -149,6 +194,14 @@ export default {
   },
   mounted () {
     this.advancedSearch()
+    SemanticService.findAllConcepts()
+      .then((response) => {
+        this.concepts = SemanticMapper.mapConcepts(response)
+      })
+    SemanticService.findAllUnits()
+      .then((response) => {
+        this.units = SemanticMapper.mapUnits(response)
+      })
   },
   methods: {
     /* Removes all advanced search fields when switching the type */
@@ -164,6 +217,12 @@ export default {
       } else {
         delete this.advancedSearchData.search_term
       }
+      if ('t1' in this.advancedSearchData && this.advancedSearchData.t1) {
+        this.advancedSearchData.t1 = Number(this.advancedSearchData.t1)
+      }
+      if ('t2' in this.advancedSearchData && this.advancedSearchData.t2) {
+        this.advancedSearchData.t2 = Number(this.advancedSearchData.t2)
+      }
       this.loading = true
       SearchService.search(this.advancedSearchData)
         .then((response) => {