diff --git a/soitool/main_window.py b/soitool/main_window.py
index a099da8f2186c4e701403a5506e0cf64c1abe3c4..e8f053c623929a089ebef73fa3f826c2333db0d1 100644
--- a/soitool/main_window.py
+++ b/soitool/main_window.py
@@ -20,6 +20,8 @@ from soitool.codebook_to_pdf import generate_codebook_pdf
 from soitool.dialog_wrappers import exec_info_dialog
 from soitool.codebook_widget import CodebookWidget
 from soitool.codebook_model_view import CodebookTableModel
+from soitool.soi_db_widget import SOIDbWidget
+from soitool.soi_model_view import SOITableModel
 from soitool.database import Database, DBPATH
 from soitool.help_actions import ShortcutsHelpDialog, BasicUsageHelpDialog
 from soitool.serialize_export_import_soi import (
@@ -109,6 +111,7 @@ class MainWindow(QMainWindow):
         open_file_db = QAction("Åpne fra DB", self)
         open_file_db.setShortcut("Ctrl+d")
         open_file_db.setStatusTip("Åpne en SOI fra databasen")
+        open_file_db.triggered.connect(self.show_soi_db)
         file_menu.addAction(open_file_db)
 
         # Preview SOI
@@ -220,8 +223,8 @@ class MainWindow(QMainWindow):
         """
         widget_in_tab = self.tabs.widget(index)
 
-        # Close db-connection if tab is a codebook-tab
-        if isinstance(widget_in_tab, CodebookWidget):
+        # Close db-connection if tab is a CodebookWidget or SOIDbWidget
+        if isinstance(widget_in_tab, (CodebookWidget, SOIDbWidget)):
             widget_in_tab.view.close_db_connection()
 
         self.tabs.removeTab(index)
@@ -307,7 +310,24 @@ class MainWindow(QMainWindow):
 
         # If tab contains an SOI
         if isinstance(tab_widget, SOIWorkspaceWidget):
+            # Update tab showing SOI's in db if it is open,
+            # and pause database-lock by codebook-tab if it is open
+            soi_db_view = None
+            codebook_db_view = None
+            for i in range(self.tabs.count()):
+                if self.tabs.tabText(i) == "SOI'er i DB":
+                    soi_db_view = self.tabs.widget(i).view
+                    soi_db_view.setModel(None)
+                elif self.tabs.tabText(i) == "Kodebok":
+                    codebook_db_view = self.tabs.widget(i).view
+                    codebook_db_view.setModel(None)
+
             self.database.insert_or_update_soi(tab_widget.soi)
+
+            if soi_db_view is not None:
+                soi_db_view.setModel(SOITableModel())
+            if codebook_db_view is not None:
+                codebook_db_view.setModel(CodebookTableModel())
         else:
             exec_info_dialog(
                 "Valgt tab er ingen SOI-tab",
@@ -315,6 +335,23 @@ class MainWindow(QMainWindow):
                 "Riktig tab må velges for å lagre en SOI i DB.",
             )
 
+    def show_soi_db(self):
+        """Open and select tab containing SOIDbWidget.
+
+        Select tab if it is already open,
+        create and select tab if not open.
+        """
+        # Loop through tabs to look for existing SOI-db-tab:
+        for i in range(self.tabs.count()):
+            if self.tabs.tabText(i) == "SOI'er i DB":
+                self.tabs.setCurrentIndex(i)
+                break
+        # SOI-db-tab does not exist, create, add and select tab
+        else:
+            tab = SOIDbWidget(self.database, self.tabs)
+            self.tabs.addTab(tab, "SOI'er i DB")
+            self.tabs.setCurrentWidget(tab)
+
     def open_shortcut_help(self):
         """Open shortcut dialog."""
         self.popup_shortcut_help.setWindowTitle("Hurtigtaster")
diff --git a/soitool/soi_db_widget.py b/soitool/soi_db_widget.py
new file mode 100644
index 0000000000000000000000000000000000000000..343c7d4672c7b7db8557cb59c5836960d2dd317b
--- /dev/null
+++ b/soitool/soi_db_widget.py
@@ -0,0 +1,19 @@
+"""Module containing a widget for viewing and opening SOI's from database."""
+from PySide2.QtWidgets import QWidget, QHBoxLayout
+from soitool.soi_model_view import SOITableView
+
+
+class SOIDbWidget(QWidget):
+    """Widget for viewing and opening SOI's from database."""
+
+    def __init__(self, database, tab_widget):
+        super().__init__()
+
+        self.view = SOITableView(database, tab_widget)
+        self.create_and_set_layout()
+
+    def create_and_set_layout(self):
+        """Create layout, add widget and set layout."""
+        hbox = QHBoxLayout()
+        hbox.addWidget(self.view)
+        self.setLayout(hbox)
diff --git a/soitool/soi_model_view.py b/soitool/soi_model_view.py
new file mode 100644
index 0000000000000000000000000000000000000000..680d27502fdefbec63c274fcd4c4c4ae1084b7b7
--- /dev/null
+++ b/soitool/soi_model_view.py
@@ -0,0 +1,148 @@
+"""GUI-interface towards database-table 'SOI'.
+
+Contains functionality for viewing and opening SOI's from database-table 'SOI',
+where (some) SOI's are stored.
+"""
+from PySide2.QtWidgets import QTableView
+from PySide2.QtSql import QSqlDatabase, QSqlTableModel
+from PySide2.QtCore import Qt
+from soitool.style import CODEBOOK_HEADER_FONT, CODEBOOK_HEADER_BACKGROUND_CSS
+from soitool.serialize_export_import_soi import construct_soi_from_serialized
+from soitool.soi_workspace_widget import SOIWorkspaceWidget
+
+# Name and type of database
+CONNAME = "SOIDB"
+DBTYPE = "QSQLITE"
+
+
+class SOITableView(QTableView):
+    """TableView with a model of the 'SOI'-table from database.
+
+    This modified QTableView creates a SOITableModel, which reads data from the
+    SOI-table. When the user double-clicks or presses the enter-key on a cell,
+    a tab containing SOIWorkspaceWidget, with the SOI from the current row, is
+    opened and selected.
+
+    Parameters
+    ----------
+    database : soitool.database.Database
+        Is used to create a QSqlDatabase from the database-file.
+    tab_widget : QTabWidget
+        Is used to open a new tab.
+
+    Raises
+    ------
+    RuntimeError
+        If database does not open.
+    """
+
+    def __init__(self, database, tab_widget):
+        super().__init__()
+        db = QSqlDatabase.addDatabase(DBTYPE, CONNAME)
+        db.setDatabaseName(database.db_path)
+        self.tab_widget = tab_widget
+
+        if not db.open():
+            raise RuntimeError("Could not open database.")
+
+        # Enable sorting
+        self.setSortingEnabled(True)
+
+        # Create and set model
+        model = SOITableModel()
+        self.setModel(model)
+
+        # Remove horizontal scrollbar, hide vertical header and 'SOI'-column
+        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.verticalHeader().hide()
+        self.hideColumn(2)
+
+        # Set horizontal header-text and it's style
+        self.set_horizontal_header_text()
+        header = self.horizontalHeader()
+        header.setFont(CODEBOOK_HEADER_FONT)
+        header.setStyleSheet(CODEBOOK_HEADER_BACKGROUND_CSS)
+
+        # Resize
+        self.resizeColumnsToContents()
+        width = (
+            self.columnWidth(0) + self.columnWidth(1) + self.columnWidth(3) + 2
+        )  # +2 offset
+        self.setFixedWidth(width)
+
+        self.doubleClicked.connect(self.open_soi_tab)
+
+    def set_horizontal_header_text(self):
+        """Set Norwegian names in horizontal header."""
+        self.model().setHeaderData(0, Qt.Horizontal, "Tittel")
+        self.model().setHeaderData(1, Qt.Horizontal, "Versjon")
+        self.model().setHeaderData(3, Qt.Horizontal, "Dato")
+
+    def keyPressEvent(self, event):
+        """Open SOI-tab if enter-key is pressed."""
+        if event.key() == Qt.Key_Return:
+            self.open_soi_tab()
+        super().keyPressEvent(event)
+
+    def open_soi_tab(self):
+        """Construct SOI and open SOIWorkspacewidget in new tab."""
+        # Get index of the current row and read compressed, serialized SOI
+        row = self.currentIndex().row()
+        compressed_soi = self.model().index(row, 2).data()
+
+        # Construct SOI and create SOIWorkspaceWidget
+        soi = construct_soi_from_serialized(compressed_soi, compressed=True)
+        tab = SOIWorkspaceWidget(soi)
+
+        # Add and select tab
+        self.tab_widget.addTab(tab, soi.title)
+        self.tab_widget.setCurrentWidget(tab)
+
+    def setModel(self, model):
+        """Set model, resize and hide 'SOI'-column.
+
+        Parameters
+        ----------
+        model : soitool.soi_model_view.SOITableModel or None
+            Model containing data to display.
+        """
+        super().setModel(model)
+        if model is not None:
+            self.hideColumn(2)
+            self.resizeColumnsToContents()
+            width = (
+                self.columnWidth(0)
+                + self.columnWidth(1)
+                + self.columnWidth(3)
+                + 2  # + 2 offset
+            )
+            self.setFixedWidth(width)
+            self.sortByColumn(3, Qt.DescendingOrder)  # Sort by 'Date'-column
+
+    def close_db_connection(self):
+        """Close connection to database."""
+        self.setModel(None)
+        QSqlDatabase.removeDatabase(CONNAME)
+
+
+class SOITableModel(QSqlTableModel):
+    """Uneditable QSqlTableModel of database-table 'SOI'."""
+
+    def __init__(self):
+        super().__init__(None, QSqlDatabase.database(CONNAME))
+        self.setTable("SOI")
+        self.select()
+        self.sort(3, Qt.DescendingOrder)  # Sort by 'Date'-column
+
+    def flags(self, index):
+        """Disable editing.
+
+        Parameters
+        ----------
+        index : QModelIndex
+            Is used to locate data in a model.
+        """
+        flags = super().flags(index)
+        flags ^= Qt.ItemIsEditable
+
+        return flags
diff --git a/test/test_database.py b/test/test_database.py
index 42c705285dbe516df3471c488d4032263c366fc1..219431d7ee2e89fb568771abfd6a2ab44f98afce 100644
--- a/test/test_database.py
+++ b/test/test_database.py
@@ -17,6 +17,9 @@ TESTDBPATH = os.path.join(SOITOOL_DIR, TESTDBNAME)
 
 TESTDATA_PATH = Path(__file__).parent.parent / "soitool/testdata"
 
+# Tolerance for timed tests. Tolerating DELTA seconds of difference
+DELTA = 10
+
 
 class DatabaseTest(unittest.TestCase):
     """Database tests."""
@@ -141,7 +144,7 @@ class DatabaseTest(unittest.TestCase):
         # Calculates difference in seconds
         time_diff = (second_time - first_time).total_seconds()
         # Compares difference with sleep_time
-        self.assertAlmostEqual(time_diff, sleep_time, delta=0.2)
+        self.assertAlmostEqual(time_diff, sleep_time, delta=DELTA)
 
     def test_get_categories(self):
         """Assert function get_categories works as expected."""
@@ -276,7 +279,7 @@ class DatabaseTest(unittest.TestCase):
         expected_time = seconds_in_24h - sleep_time
         actual_time = self.database.seconds_to_next_update(seconds_in_24h)
         # Compares expected and function return value with
-        self.assertAlmostEqual(expected_time, actual_time, delta=0.2)
+        self.assertAlmostEqual(expected_time, actual_time, delta=DELTA)
 
     def teset_seconds_to_next_update_complete_period(self):
         """Check that seconds to next update can returns 0 and not negative."""