Oracle中TO_DATE格式收集

本文详细解读了TO_DATE格式及其在日期转换、字符转换、求星期几、两个日期之间的天数、时间范围设定等场景的应用,并提供了实例代码。通过实际案例,展示了如何灵活运用日期和字符转换函数,解决日期相关的复杂问题。
TO_DATE格式(以时间:2007-11-02   13:45:25为例)
   
        Year:      
        yy two digits 两位年                显示值:07
        yyy three digits 三位年                显示值:007
        yyyy four digits 四位年                显示值:2007
            
        Month:      
        mm    number     两位月              显示值:11
        mon    abbreviated 字符集表示          显示值:11月,若是英文版,显示nov     
        month spelled out 字符集表示          显示值:11月,若是英文版,显示november 
          
        Day:      
        dd    number         当月第几天        显示值:02
        ddd    number         当年第几天        显示值:02
        dy    abbreviated 当周第几天简写    显示值:星期五,若是英文版,显示fri
        day    spelled out   当周第几天全写    显示值:星期五,若是英文版,显示friday        
        ddspth spelled out, ordinal twelfth 
             
              Hour:
              hh    two digits 12小时进制            显示值:01
              hh24 two digits 24小时进制            显示值:13
              
              Minute:
              mi    two digits 60进制                显示值:45
              
              Second:
              ss    two digits 60进制                显示值:25
              
              其它
              Q     digit         季度                  显示值:4
              WW    digit         当年第几周            显示值:44
              W    digit          当月第几周            显示值:1
              
        24小时格式下时间范围为: 0:00:00 - 23:59:59....      
        12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 
            
1. 日期和字符转换函数用法(to_date,to_char)
         
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual;   //日期转化为字符串   
select to_char(sysdate,'yyyy') as nowYear   from dual;   //获取时间的年   
select to_char(sysdate,'mm')    as nowMonth from dual;   //获取时间的月   
select to_char(sysdate,'dd')    as nowDay    from dual;   //获取时间的日   
select to_char(sysdate,'hh24') as nowHour   from dual;   //获取时间的时   
select to_char(sysdate,'mi')    as nowMinute from dual;   //获取时间的分   
select to_char(sysdate,'ss')    as nowSecond from dual;   //获取时间的秒 
    
select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss')    from dual//

2.      
    select to_char( to_date(222,'J'),'Jsp') from dual      
    
    显示Two Hundred Twenty-Two     

3.求某天是星期几      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;      
   星期一      
   select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
   monday      
   设置日期语言      
   ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';      
   也可以这样      
   TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')     

4. 两个日期间的天数      
    select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;     

5. 时间为null的用法      
   select id, active_date from table1      
   UNION      
   select 1, TO_DATE(null) from dual;      
   
   注意要用TO_DATE(null)     

6.月份差   
   a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')      
   那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。      
   所以,当时间需要精确的时候,觉得to_char还是必要的 
      
7. 日期格式冲突问题      
    输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'      
    alter system set NLS_DATE_LANGUAGE = American      
    alter session set NLS_DATE_LANGUAGE = American      
    或者在to_date中写      
    select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;      
    注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,      
    可查看      
    select * from nls_session_parameters      
    select * from V$NLS_PARAMETERS     

8.      
   select count(*)      
   from ( select rownum-1 rnum      
       from all_objects      
       where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-      
       02-01','yyyy-mm-dd')+1      
      )      
   where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )      
        not in ( '1', '7' )      
   
   查找2002-02-28至2002-02-01间除星期一和七的天数      
   在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).     

9. 查找月份     
    select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1      
   select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;      
    1.03225806451613 
       
10. Next_day的用法      
    Next_day(date, day)      
    
    Monday-Sunday, for format code DAY      
    Mon-Sun, for format code DY      
    1-7, for format code D     

11      
   select to_char(sysdate,'hh:mi:ss') TIME from all_objects      
   注意:第一条记录的TIME 与最后一行是一样的      
   可以建立一个函数来处理这个问题      
   create or replace function sys_date return date is      
   begin      
   return sysdate;      
   end;      
   
   select to_char(sys_date,'hh:mi:ss') from all_objects;   
     
12.获得小时数      
     extract()找出日期或间隔值的字段值
    SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer      
    SQL> select sysdate ,to_char(sysdate,'hh') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH')      
    -------------------- ---------------------      
    2003-10-13 19:35:21 07      
    
    SQL> select sysdate ,to_char(sysdate,'hh24') from dual;      
    
    SYSDATE TO_CHAR(SYSDATE,'HH24')      
    -------------------- -----------------------      
    2003-10-13 19:35:21 19     

       
13.年月日的处理      
   select older_date,      
       newer_date,      
       years,      
       months,      
       abs(      
        trunc(      
         newer_date-      
         add_months( older_date,years*12+months )      
        )      
       ) days 
       
   from ( select      
        trunc(months_between( newer_date, older_date )/12) YEARS,      
        mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS,      
        newer_date,      
        older_date      
        from ( 
              select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date      
              from emp 
             )      
      )     

14.处理月份天数不定的办法      
   select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual     

16.找出今年的天数      
   select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual     

   闰年的处理方法      
   to_char( last_day( to_date('02'    | | :year,'mmyyyy') ), 'dd' )      
   如果是28就不是闰年     

17.yyyy与rrrr的区别      
   'YYYY99 TO_C      
   ------- ----      
   yyyy 99 0099      
   rrrr 99 1999      
   yyyy 01 0001      
   rrrr 01 2001     

18.不同时区的处理      
   select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate      
   from dual;     

19.5秒钟一个间隔      
   Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')      
   from dual     

   2002-11-1 9:55:00 35786      
   SSSSS表示5位秒数     

20.一年的第几天      
   select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
        
   310 2002-11-6 10:03:51     

21.计算小时,分,秒,毫秒      
    select      
     Days,      
     A,      
     TRUNC(A*24) Hours,      
     TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,      
     TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,      
     TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds      
    from      
    (      
     select      
     trunc(sysdate) Days,      
     sysdate - trunc(sysdate) A      
     from dual      
   )     


   select * from tabname      
   order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');      
   
   //      
   floor((date2-date1) /365) 作为年      
   floor((date2-date1, 365) /30) 作为月      
   d(mod(date2-date1, 365), 30)作为日.

23.next_day函数      返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
   next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。      
   1 2 3 4 5 6 7      
   日 一 二 三 四 五 六    
   
   --------------------------------------------------------------- 
   
   select    (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from ddual
   日期 返回的是天 然后 转换为ss
     
24,round[舍入到最接近的日期](day:舍入到最接近的星期日)
   select sysdate S1,
   round(sysdate) S2 ,
   round(sysdate,'year') YEAR,
   round(sysdate,'month') MONTH ,
   round(sysdate,'day') DAY from dual

25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型
   select sysdate S1,                     
     trunc(sysdate) S2,                 //返回当前日期,无时分秒
     trunc(sysdate,'year') YEAR,        //返回当前年的1月1日,无时分秒
     trunc(sysdate,'month') MONTH ,     //返回当前月的1日,无时分秒
     trunc(sysdate,'day') DAY           //返回当前星期的星期天,无时分秒
   from dual

26,返回日期列表中最晚日期
   select greatest('01-1月-04','04-1月-04','10-2月-04') from dual

27.计算时间差
     注:oracle时间差是以天数为单位,所以换算成年月,日
     
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual        //时间差-年
      select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual        //时间差-月
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual             //时间差-天
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual         //时间差-时
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual    //时间差-分
      select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒

28.更新时间
     注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual        //改变时间-年
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual                                 //改变时间-月
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual            //改变时间-日
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual         //改变时间-时
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual      //改变时间-分
     select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual   //改变时间-秒

29.查找月的第一天,最后一天
     SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month,
       Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month,
       LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month
   FROM dual;

一个Python 作为Sqlite 数据传输同步到Oracle ,源码 import sqlite3 import oracledb from datetime import datetime, timedelta import logging import re # 日志配置 logging.basicConfig( filename='db_sync_debug.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', encoding='utf-8' ) # 增强的日期格式正则表达式 DATE_REGEX = re.compile( r'^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?$' ) # 主键映射表 TABLE_PRIMARY_KEYS = { "OEE_AvaiableTime": "OEE_AvaiableTimeId", "OEE_CycleTime": "OEE_CycleTimeId", "OEE_CycleTime_Config": "OEE_CycleTimeConfigId", "OEE_LineReport": "OEE_LineReportId", "OEE_PerformanceComment": "OEE_PerformanceCommentId", "OEE_ProductStatus": "OEE_ProductStatusId", "OEE_Quality": "OEE_QualityId", "OEE_ShiftPlan_Config": "OEE_ShiftPlanConfigId", "OEE_ShiftWorkTime": "OEE_ShiftWorkTimeId", "OEE_Target_Config": "OEE_TargetConfigId" } # Oracle 关键字列表(扩展) ORACLE_KEYWORDS = { 'ACCESS', 'ADD', 'ALL', 'ALTER', 'AND', 'ANY', 'AS', 'ASC', 'AUDIT', 'BETWEEN', 'BY', 'CHAR', 'CHECK', 'CLUSTER', 'COLUMN', 'COMMENT', 'COMPRESS', 'CONNECT', 'CREATE', 'CURRENT', 'DATE', 'DECIMAL', 'DEFAULT', 'DELETE', 'DESC', 'DISTINCT', 'DROP', 'ELSE', 'EXCLUSIVE', 'EXISTS', 'FILE', 'FLOAT', 'FOR', 'FROM', 'GRANT', 'GROUP', 'HAVING', 'IDENTIFIED', 'IMMEDIATE', 'IN', 'INCREMENT', 'INDEX', 'INITIAL', 'INSERT', 'INTEGER', 'INTERSECT', 'INTO', 'IS', 'LEVEL', 'LIKE', 'LOCK', 'LONG', 'MAXEXTENTS', 'MINUS', 'MLSLABEL', 'MODE', 'MODIFY', 'NOAUDIT', 'NOCOMPRESS', 'NOT', 'NOWAIT', 'NULL', 'NUMBER', 'OF', 'OFFLINE', 'ON', 'ONLINE', 'OPTION', 'OR', 'ORDER', 'PCTFREE', 'PRIOR', 'PRIVILEGES', 'PUBLIC', 'RAW', 'RENAME', 'RESOURCE', 'REVOKE', 'ROW', 'ROWID', 'ROWNUM', 'ROWS', 'SELECT', 'SESSION', 'SET', 'SHARE', 'SIZE', 'SMALLINT', 'START', 'SUCCESSFUL', 'SYNONYM', 'SYSDATE', 'TABLE', 'THEN', 'TO', 'TRIGGER', 'UID', 'UNION', 'UNIQUE', 'UPDATE', 'USER', 'VALIDATE', 'VALUES', 'VARCHAR', 'VARCHAR2', 'VIEW', 'WHENEVER', 'WHERE', 'WITH', 'TYPE', 'MI', 'SS' # 添加了额外的关键字 } def generate_bind_name(col_name, is_date=False): """生成安全的绑定变量名""" base_name = col_name.lower().replace(' ', '_') if is_date: base_name = f"{base_name}_dt" if base_name.upper() in ORACLE_KEYWORDS: base_name = f"_{base_name}_" if re.search(r'[^a-z0-9_]', base_name): base_name = f"_{base_name}_" return base_name def validate_bind_variables(sql, params): """ 改进的绑定变量验证: 1. 修复未初始化变量问题 2. 增强字符串字面值处理 """ bind_names = set() in_string = False current_name = "" collecting = False # 关键初始化 # 解析SQL查找所有绑定变量占位符 for char in sql: # 处理字符串字面值开始/结束 if char == "'": in_string = not in_string continue # 只在非字符串区域处理 if not in_string: # 遇到冒号开始收集 if char == ':': collecting = True continue # 收集有效绑定变量名字符 if collecting and (char.isalnum() or char == '_'): current_name += char continue # 结束当前绑定变量名收集 if collecting and current_name: bind_names.add(current_name) current_name = "" collecting = False # 处理最后一个绑定变量(如果存在) if collecting and current_name: bind_names.add(current_name) # 验证参数匹配 param_keys = set(params.keys()) missing = bind_names - param_keys extra = param_keys - bind_names if missing: logging.warning(f"SQL中有但参数字典中缺失的绑定变量: {missing}") return False if extra: logging.warning(f"参数字典中有但SQL中未使用的绑定变量: {extra}") return False return True def debug_log_sql(sql, params): """安全的SQL日志记录,避免错误替换字符串字面值""" logging.debug("SQL语句:") logging.debug(sql) logging.debug("绑定参数:") safe_params = {} for k, v in params.items(): if isinstance(v, str) and len(v) > 50: safe_params[k] = f"[{v[:20]}...]" else: safe_params[k] = v logging.debug(safe_params) def generate_insert_sql(table, columns, oracle_columns, row_data): """更健壮的INSERT SQL生成器""" cols = [] values = [] bind_params = {} for col in columns: col_upper = col.upper() if col_upper not in oracle_columns: continue col_type = oracle_columns[col_upper] value = row_data[col] # 生成安全的绑定变量名 is_date_field = "DATE" in col_type or "TIMESTAMP" in col_type bind_name = generate_bind_name(col, is_date_field) # 处理日期字段 if is_date_field: values.append(f"TO_DATE(:{bind_name}, 'YYYY-MM-DD HH24:MI:SS')") bind_params[bind_name] = value # 处理NULL值 elif value is None: values.append("NULL") else: values.append(f":{bind_name}") bind_params[bind_name] = value cols.append(f'"{col_upper}"') cols_str = ", ".join(cols) values_str = ", ".join(values) sql = f"INSERT INTO {table} ({cols_str}) VALUES ({values_str})" # 验证绑定变量匹配性 if not validate_bind_variables(sql, bind_params): logging.error("生成的SQL绑定变量验证失败!") return sql, bind_params def sync_sqlite_to_oracle(sqlite_db, oracle_dsn, username, password, tables, test_mode): """最终优化的数据库同步方案""" # 计算时间范围 - 支持测试模式 if test_mode: # 指定固定测试时间范围 start_time = '2025-10-05 08:20:00' end_time = '2025-10-06 08:20:00' else: # 动态计算时间范围 now = datetime.datetime.now() start_time = (now - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S') end_time = now.strftime('%Y-%m-%d %H:%M:%S') logging.info(f"同步时间范围: {start_time} 到 {end_time}") try: sqlite_conn = sqlite3.connect(sqlite_db) sqlite_cursor = sqlite_conn.cursor() oracle_conn = oracledb.connect( user=username, password=password, dsn=oracle_dsn ) oracle_cursor = oracle_conn.cursor() # 设置Oracle会话日期格式 oracle_cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'") oracle_conn.commit() for table in tables: primary_key = TABLE_PRIMARY_KEYS.get(table) if not primary_key: logging.error(f"未定义主键的表: {table}") continue logging.info(f"开始同步表: {table}, 主键: {primary_key}") # 获取SQLite表结构 sqlite_cursor.execute(f"PRAGMA table_info({table})") columns = [col[1] for col in sqlite_cursor.fetchall()] # 获取Oracle列信息 oracle_cursor.execute(""" SELECT column_name, data_type FROM user_tab_columns WHERE table_name = UPPER(:table_name) """, table_name=table) oracle_columns = {col[0].upper(): col[1].upper() for col in oracle_cursor.fetchall()} # 查询变更记录 sqlite_cursor.execute(f""" SELECT * FROM {table} WHERE UpdateAt BETWEEN ? AND ? """, (start_time, end_time)) rows = sqlite_cursor.fetchall() for row in rows: row_dict = dict(zip(columns, row)) oracle_compatible_data = {} # 格式化数据为Oracle兼容格式 for col_name, value in row_dict.items(): col_upper = col_name.upper() if col_upper in oracle_columns: col_type = oracle_columns[col_upper] # 处理日期字段 if "DATE" in col_type or "TIMESTAMP" in col_type: formatted = format_date_value(value) oracle_compatible_data[col_name] = formatted if formatted else value else: oracle_compatible_data[col_name] = value else: oracle_compatible_data[col_name] = value # 检查记录是否存在 pk_value = oracle_compatible_data[primary_key] oracle_cursor.execute(f""" SELECT COUNT(*) FROM {table} WHERE "{primary_key.upper()}" = :pk_value """, pk_value=pk_value) if oracle_cursor.fetchone()[0] > 0: # 更新记录 update_sql, update_params = generate_update_sql( table, columns, primary_key, oracle_columns, oracle_compatible_data ) sql_to_execute = update_sql params_to_execute = update_params else: # 插入记录 insert_sql, insert_params = generate_insert_sql( table, columns, oracle_columns, oracle_compatible_data ) sql_to_execute = insert_sql params_to_execute = insert_params # 执行SQL try: debug_log_sql(sql_to_execute, params_to_execute) oracle_cursor.execute(sql_to_execute, params_to_execute) except oracledb.DatabaseError as e: handle_oracle_error(e, sql_to_execute, params_to_execute) raise oracle_conn.commit() logging.info(f"{table} 同步完成") logging.info("所有表同步成功") except Exception as e: logging.error(f"同步失败: {str(e)}", exc_info=True) if 'oracle_conn' in locals(): oracle_conn.rollback() finally: if 'sqlite_conn' in locals(): sqlite_conn.close() if 'oracle_conn' in locals(): oracle_conn.close() def format_date_value(value): """格式化日期值为Oracle兼容格式""" if isinstance(value, str): match = DATE_REGEX.match(value) if match: groups = match.groups() return f"{groups[0]}-{groups[1]}-{groups[2]} {groups[3]}:{groups[4]}:{groups[5]}" elif isinstance(value, datetime): return value.strftime('%Y-%m-%d %H:%M:%S') return value def handle_oracle_error(error, sql, params): """详细的Oracle错误处理""" try: error_obj = error.args[0] logging.error(f"Oracle错误: {error_obj.message} (代码: {error_obj.code})") except: logging.error(f"数据库错误: {str(error)}") logging.error(f"问题SQL: {sql}") logging.error(f"绑定参数: {params}") # 提供具体解决方案 if "ORA-01745" in str(error): logging.error("解决方案: 检查绑定变量名是否包含无效字符或Oracle关键字") elif "DPY-4008" in str(error): logging.error("解决方案: 确保所有绑定变量在SQL和参数字典中精确匹配") logging.error("检查步骤: 使用validate_bind_variables函数验证一致性") def generate_update_sql(table, columns, primary_key, oracle_columns, row_data): """更健壮的UPDATE SQL生成器""" set_clauses = [] bind_params = {} for col in columns: if col == primary_key: continue col_upper = col.upper() if col_upper not in oracle_columns: continue col_type = oracle_columns[col_upper] value = row_data[col] # 生成安全的绑定变量名 is_date_field = "DATE" in col_type or "TIMESTAMP" in col_type bind_name = generate_bind_name(col, is_date_field) # 处理日期字段 if is_date_field: set_clauses.append(f'"{col_upper}" = TO_DATE(:{bind_name}, \'YYYY-MM-DD HH24:MI:SS\')') bind_params[bind_name] = value # 处理NULL值 elif value is None: set_clauses.append(f'"{col_upper}" = NULL') else: set_clauses.append(f'"{col_upper}" = :{bind_name}') bind_params[bind_name] = value # 添加主键条件 pk_bind_name = generate_bind_name(primary_key) bind_params[pk_bind_name] = row_data[primary_key] set_clause = ", ".join(set_clauses) sql = f"UPDATE {table} SET {set_clause} WHERE \"{primary_key.upper()}\" = :{pk_bind_name}" # 验证绑定变量匹配性 if not validate_bind_variables(sql, bind_params): logging.error("生成的SQL绑定变量验证失败!") return sql, bind_params if __name__ == "__main__": # 配置参数 SQLITE_DB = "D:\\IISwebOEE\\App_Data\\webFrameworkEF6.db" ORACLE_DSN = "at3-pacc-f2db.zf-world.com/AT3PACC2" USERNAME = "acc_oee2" PASSWORD = "accZF_2025" TABLES = [ "OEE_AvaiableTime", "OEE_CycleTime", "OEE_LineReport", "OEE_PerformanceComment", "OEE_ProductStatus", "OEE_Quality", "OEE_ShiftPlan_Config", "OEE_ShiftWorkTime", "OEE_Target_Config", "OEE_CycleTime_Config" ] # 启用测试模式使用固定时间范围 sync_sqlite_to_oracle( SQLITE_DB, ORACLE_DSN, USERNAME, PASSWORD, TABLES, test_mode=True # 启用测试模式 ) 目前是遇到问题 2025-11-07 09:42:42,481 - INFO - 开始同步表: OEE_AvaiableTime, 主键: OEE_AvaiableTimeId 2025-11-07 09:42:47,025 - DEBUG - SQL语句: 2025-11-07 09:42:47,025 - DEBUG - INSERT INTO OEE_AvaiableTime ("OEE_AVAIABLETIMEID", "STARTTIME", "ENDTIME", "DURATION", "TYPE", "OP", "PARTNO", "LOSSREASON", "COMMENT", "SHIFTWORKTIMEID", "CREATEAT", "UPDATEAT", "BYUSER") VALUES (:oee_avaiabletimeid, :starttime, :endtime, :duration, :_type_, NULL, NULL, NULL, :_comment_, :shiftworktimeid, TO_DATE(:createat_dt, 'YYYY-MM-DD HH24:MI:SS'), TO_DATE(:updateat_dt, 'YYYY-MM-DD HH24:MI:SS'), :byuser) 2025-11-07 09:42:47,025 - DEBUG - 绑定参数: 2025-11-07 09:42:47,025 - DEBUG - {'oee_avaiabletimeid': '6b245d77-56ae-429e-809b-f8b71ddf19fb', 'starttime': '176', 'endtime': '179', 'duration': 15, '_type_': '13', '_comment_': '2人,22小时', 'shiftworktimeid': 'd3369a2c-5097-4654-b63c-4a7812b6e54b', 'createat_dt': '2025-10-04 12:37:08', 'updateat_dt': '2025-10-05 18:51:51', 'byuser': 'AD'} 2025-11-07 09:42:47,026 - ERROR - Oracle错误: DPY-4008: no bind placeholder named ":_type_" was found in the SQL text (代码: 0) 2025-11-07 09:42:47,026 - ERROR - 问题SQL: INSERT INTO OEE_AvaiableTime ("OEE_AVAIABLETIMEID", "STARTTIME", "ENDTIME", "DURATION", "TYPE", "OP", "PARTNO", "LOSSREASON", "COMMENT", "SHIFTWORKTIMEID", "CREATEAT", "UPDATEAT", "BYUSER") VALUES (:oee_avaiabletimeid, :starttime, :endtime, :duration, :_type_, NULL, NULL, NULL, :_comment_, :shiftworktimeid, TO_DATE(:createat_dt, 'YYYY-MM-DD HH24:MI:SS'), TO_DATE(:updateat_dt, 'YYYY-MM-DD HH24:MI:SS'), :byuser) 2025-11-07 09:42:47,026 - ERROR - 绑定参数: {'oee_avaiabletimeid': '6b245d77-56ae-429e-809b-f8b71ddf19fb', 'starttime': '176', 'endtime': '179', 'duration': 15, '_type_': '13', '_comment_': '2人,22小时', 'shiftworktimeid': 'd3369a2c-5097-4654-b63c-4a7812b6e54b', 'createat_dt': '2025-10-04 12:37:08', 'updateat_dt': '2025-10-05 18:51:51', 'byuser': 'AD'} 2025-11-07 09:42:47,026 - ERROR - 解决方案: 确保所有绑定变量在SQL和参数字典中精确匹配 2025-11-07 09:42:47,027 - ERROR - 检查步骤: 使用validate_bind_variables函数验证一致性 2025-11-07 09:42:47,027 - ERROR - 同步失败: DPY-4008: no bind placeholder named ":_type_" was found in the SQL text Traceback (most recent call last): File "C:\UserData\Python\SyncSqlitedb\sync_service.py", line 275, in sync_sqlite_to_oracle oracle_cursor.execute(sql_to_execute, params_to_execute) ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\guc3\AppData\Roaming\Python\Python313\site-packages\oracledb\cursor.py", line 708, in execute impl.execute(self) ~~~~~~~~~~~~^^^^^^ File "src/oracledb/impl/thin/cursor.pyx", line 275, in oracledb.thin_impl.ThinCursorImpl.execute File "src/oracledb/impl/thin/cursor.pyx", line 182, in oracledb.thin_impl.BaseThinCursorImpl._preprocess_execute File "src/oracledb/impl/base/cursor.pyx", line 351, in oracledb.base_impl.BaseCursorImpl._perform_binds File "src/oracledb/impl/thin/var.pyx", line 95, in oracledb.thin_impl.ThinVarImpl._bind File "C:\Users\guc3\AppData\Roaming\Python\Python313\site-packages\oracledb\errors.py", line 199, in _raise_err raise error.exc_type(error) from cause oracledb.exceptions.DatabaseError: DPY-4008: no bind placeholder named ":_type_" was found in the SQL text 请帮忙解决
最新发布
11-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值