diff --git ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 4691abb73c63..586e0aa4e777 100644
--- ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -841,7 +841,24 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, bool bRegisterOGR2SQLit
           CPLTestBool(CSLFetchNameValueDef(papszOpenOptions, "NOLOCK", "NO")) )
     {
         m_osFilenameForSQLiteOpen = "file:";
-        m_osFilenameForSQLiteOpen += m_pszFilename;
+
+        // Apply rules from "3.1. The URI Path" of https://www.sqlite.org/uri.html
+        CPLString osFilenameForURI(m_pszFilename);
+        osFilenameForURI.replaceAll('?', "%3f");
+        osFilenameForURI.replaceAll('#', "%23");
+#ifdef _WIN32
+        osFilenameForURI.replaceAll('\\', '/');
+#endif
+        osFilenameForURI.replaceAll("//", '/');
+#ifdef _WIN32
+        if( osFilenameForURI.size() > 3 && osFilenameForURI[1] == ':' &&
+            osFilenameForURI[2] == '/' )
+        {
+            osFilenameForURI = '/' + osFilenameForURI;
+        }
+#endif
+
+        m_osFilenameForSQLiteOpen += osFilenameForURI;
         m_osFilenameForSQLiteOpen += "?nolock=1";
     }
 #endif
