mdbq 3.8.14__py3-none-any.whl → 3.8.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mdbq/__version__.py CHANGED
@@ -1 +1 @@
1
- VERSION = '3.8.14'
1
+ VERSION = '3.8.16'
@@ -3906,9 +3906,6 @@ def date_table():
3906
3906
  table_name='日期表',
3907
3907
  move_insert=True, # 先删除,再插入
3908
3908
  df_sql=False, # 值为 True 时使用 df.to_sql 函数上传整个表, 不会排重
3909
- drop_duplicates=False, # 值为 True 时检查重复数据再插入,反之直接上传,会比较慢
3910
- count=None,
3911
- filename=None, # 用来追踪处理进度
3912
3909
  set_typ=set_typ,
3913
3910
  )
3914
3911
 
mdbq/mysql/mysql.py CHANGED
@@ -191,7 +191,7 @@ class MysqlUpload:
191
191
  with connection.cursor() as cursor:
192
192
  # 1. 查询表, 不存在则创建一个空表
193
193
  sql = "SHOW TABLES LIKE %s;" # 有特殊字符不需转义
194
- cursor.execute(sql, (table_name))
194
+ cursor.execute(sql, (table_name,))
195
195
  if not cursor.fetchone():
196
196
  sql = f"CREATE TABLE IF NOT EXISTS `{table_name}` (id INT AUTO_INCREMENT PRIMARY KEY);"
197
197
  cursor.execute(sql)
@@ -201,7 +201,7 @@ class MysqlUpload:
201
201
  dtypes, dict_data = self.cover_dict_dtypes(dict_data=dict_data) # {'店铺名称': 'varchar(100)',...}
202
202
  if set_typ:
203
203
  # 更新自定义的列数据类型
204
- for k, v in dtypes.items():
204
+ for k, v in dtypes.copy().items():
205
205
  # 确保传进来的 set_typ 键存在于实际的 df 列才 update
206
206
  [dtypes.update({k: inside_v}) for inside_k, inside_v in set_typ.items() if k == inside_k]
207
207
 
@@ -239,48 +239,49 @@ class MysqlUpload:
239
239
  cursor.execute(sql, (db_name, table_name))
240
240
  columns = cursor.fetchall()
241
241
  cols_exist = [col['COLUMN_NAME'] for col in columns] # 数据表的所有列, 返回 list
242
- update_col = [item for item in cols_exist if item not in icm_update and item != 'id'] # 除了主键外的其他列
243
-
244
- # 构造查询条件(参数化)
245
- condition = ' AND '.join([f'`{up_col}` = %s' for up_col in icm_update])
246
- condition_values = [dict_data[up_col] for up_col in icm_update]
247
-
248
- # 执行查询(参数化)
249
- sql = f"SELECT {','.join([f'`{col}`' for col in update_col])} FROM `{table_name}` WHERE {condition}"
250
- cursor.execute(sql, condition_values)
242
+ # 保留原始列名,不提前转义
243
+ raw_update_col = [item for item in cols_exist if item not in icm_update and item != 'id'] # 除了主键外的其他列
244
+
245
+ # 构建条件参数(使用原始列名)
246
+ condition_params = []
247
+ condition_parts = []
248
+ for up_col in icm_update:
249
+ condition_parts.append(f"`{up_col}` = %s") # SQL 转义
250
+ condition_params.append(dict_data[up_col]) # 原始列名用于访问数据
251
+
252
+ # 动态转义列名生成 SQL 查询字段
253
+ escaped_update_col = [f'`{col}`' for col in raw_update_col]
254
+ sql = f"""SELECT {','.join(escaped_update_col)} FROM `{table_name}` WHERE {' AND '.join(condition_parts)}"""
255
+ cursor.execute(sql, condition_params)
251
256
  results = cursor.fetchall()
252
257
 
253
- if results: # 有数据返回,再进行增量检查
254
- for result in results: # results 是数据库数据, dict_data 是传进来的数据
255
- change_col = [] # 发生变化的列名
256
- change_values = [] # 发生变化的数据
257
- for col in update_col:
258
- # 因为 mysql 里面有 decimal 数据类型,要移除末尾的 0 再做比较(df 默认将 5.00 小数截断为 5.0)
259
- df_value = str(dict_data[col])
260
- mysql_value = str(result[col])
258
+ if results:
259
+ for result in results:
260
+ change_col = []
261
+ change_placeholders = []
262
+ set_params = []
263
+ for raw_col in raw_update_col:
264
+ # 使用原始列名访问数据
265
+ df_value = str(dict_data[raw_col])
266
+ mysql_value = str(result[raw_col])
267
+
268
+ # 清理小数点后多余的零
261
269
  if '.' in df_value:
262
- df_value = re.sub(r'0+$', '', df_value)
263
- df_value = re.sub(r'\.$', '', df_value)
270
+ df_value = re.sub(r'0+$', '', df_value).rstrip('.')
264
271
  if '.' in mysql_value:
265
- mysql_value = re.sub(r'0+$', '', mysql_value)
266
- mysql_value = re.sub(r'\.$', '', mysql_value)
267
- if df_value != mysql_value: # 传进来的数据和数据库比较, 有变化
268
- change_values += [f"`{col}` = \"{str(dict_data[col])}\""]
269
- change_col.append(col)
270
- not_change_col = [item for item in update_col if item not in change_col]
271
-
272
- # 构造更新语句(参数化)
273
- if change_values:
274
- set_clause = ', '.join([f'`{col}` = %s' for col in change_col])
275
- update_values = [dict_data[col] for col in change_col]
276
- # 添加未变化列的查询条件
277
- if not_change_col:
278
- not_change_condition = ' AND '.join([f'`{col}` = %s' for col in not_change_col])
279
- condition += f' AND {not_change_condition}'
280
- condition_values += [dict_data[col] for col in not_change_col]
281
- # 执行更新
282
- sql = f"UPDATE `{table_name}` SET {set_clause} WHERE {condition}"
283
- cursor.execute(sql, update_values + condition_values)
272
+ mysql_value = re.sub(r'0+$', '', mysql_value).rstrip('.')
273
+
274
+ if df_value != mysql_value:
275
+ change_placeholders.append(f"`{raw_col}` = %s") # 动态转义列名
276
+ set_params.append(dict_data[raw_col])
277
+ change_col.append(raw_col)
278
+
279
+ if change_placeholders:
280
+ full_params = set_params + condition_params
281
+ sql = f"""UPDATE `{table_name}`
282
+ SET {','.join(change_placeholders)}
283
+ WHERE {' AND '.join(condition_parts)}"""
284
+ cursor.execute(sql, full_params)
284
285
  else: # 没有数据返回,则直接插入数据
285
286
  # 参数化插入
286
287
  cols = ', '.join([f'`{k}`' for k in dict_data.keys()])
@@ -308,7 +309,7 @@ class MysqlUpload:
308
309
  connection.rollback()
309
310
  connection.close()
310
311
 
311
- @try_except
312
+ # @try_except
312
313
  def dict_to_mysql(self, db_name, table_name, dict_data, icm_update=None, index_length=100, set_typ=None, allow_not_null=False, cut_data=None):
313
314
  """
314
315
  插入字典数据
@@ -355,7 +356,7 @@ class MysqlUpload:
355
356
  with connection.cursor() as cursor:
356
357
  # 1. 查询表, 不存在则创建一个空表
357
358
  sql = "SHOW TABLES LIKE %s;" # 有特殊字符不需转义
358
- cursor.execute(sql, (table_name))
359
+ cursor.execute(sql, (table_name,))
359
360
  if not cursor.fetchone():
360
361
  sql = f"CREATE TABLE IF NOT EXISTS `{table_name}` (id INT AUTO_INCREMENT PRIMARY KEY);"
361
362
  cursor.execute(sql)
@@ -365,7 +366,7 @@ class MysqlUpload:
365
366
  dtypes, dict_data = self.cover_dict_dtypes(dict_data=dict_data) # {'店铺名称': 'varchar(100)',...}
366
367
  if set_typ:
367
368
  # 更新自定义的列数据类型
368
- for k, v in dtypes.items():
369
+ for k, v in dtypes.copy().items():
369
370
  # 确保传进来的 set_typ 键存在于实际的 df 列才 update
370
371
  [dtypes.update({k: inside_v}) for inside_k, inside_v in set_typ.items() if k == inside_k]
371
372
 
@@ -398,43 +399,49 @@ class MysqlUpload:
398
399
  sql = """SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s"""
399
400
  cursor.execute(sql, (db_name, table_name))
400
401
  cols_exist = [col['COLUMN_NAME'] for col in cursor.fetchall()] # 数据表的所有列, 返回 list
401
- update_col = [item for item in cols_exist if item not in icm_update and item != 'id'] # 除了主键外的其他列
402
402
 
403
- # 参数化构建查询条件
403
+ # 保留原始列名,不提前转义
404
+ raw_update_col = [item for item in cols_exist if item not in icm_update and item != 'id']
405
+
406
+ # 构建条件参数(使用原始列名)
404
407
  condition_params = []
405
408
  condition_parts = []
406
409
  for up_col in icm_update:
407
- condition_parts.append(f"`{up_col}` = %s")
408
- condition_params.append(dict_data[up_col])
410
+ condition_parts.append(f"`{up_col}` = %s") # SQL 转义
411
+ condition_params.append(dict_data[up_col]) # 原始列名访问数据
409
412
 
410
- sql = f"""SELECT `{','.join(update_col)}` FROM `{table_name}` WHERE {' AND '.join(condition_parts)}"""
413
+ # 动态转义列名生成 SQL 查询字段
414
+ escaped_update_col = [f'`{col}`' for col in raw_update_col]
415
+ sql = f"""SELECT {','.join(escaped_update_col)} FROM `{table_name}` WHERE {' AND '.join(condition_parts)}"""
411
416
  cursor.execute(sql, condition_params)
412
417
  results = cursor.fetchall()
413
- if results: # 有数据返回,再进行增量检查
414
- for result in results: # results 是数据库数据, dict_data 是传进来的数据
415
- change_col = [] # 发生变化的列名
416
- change_values = [] # 发生变化的数据
417
- for col in update_col:
418
- # 因为 mysql 里面有 decimal 数据类型,要移除末尾的 0 再做比较(df 默认将 5.00 小数截断为 5.0)
419
- df_value = str(dict_data[col])
420
- mysql_value = str(result[col])
418
+
419
+ if results:
420
+ for result in results:
421
+ change_col = []
422
+ change_placeholders = []
423
+ set_params = []
424
+ for raw_col in raw_update_col:
425
+ # 使用原始列名访问数据
426
+ df_value = str(dict_data[raw_col])
427
+ mysql_value = str(result[raw_col])
428
+
429
+ # 清理小数点后多余的零
421
430
  if '.' in df_value:
422
- df_value = re.sub(r'0+$', '', df_value)
423
- df_value = re.sub(r'\.$', '', df_value)
431
+ df_value = re.sub(r'0+$', '', df_value).rstrip('.')
424
432
  if '.' in mysql_value:
425
- mysql_value = re.sub(r'0+$', '', mysql_value)
426
- mysql_value = re.sub(r'\.$', '', mysql_value)
427
- if df_value != mysql_value: # 传进来的数据和数据库比较, 有变化
428
- change_values += [f"`{col}` = \"{str(dict_data[col])}\""]
429
- change_col.append(col)
430
- # change_values 是 df 传进来且和数据库对比后,发生了变化的数据,值示例: [`品销宝余额` = '9999.0', `短信剩余` = '888']
431
- if change_values: # change_values 有数据返回,表示值需要更新
432
- set_params = [dict_data[col] for col in change_col]
433
- full_params = set_params + condition_params # 正确顺序
433
+ mysql_value = re.sub(r'0+$', '', mysql_value).rstrip('.')
434
+
435
+ if df_value != mysql_value:
436
+ change_placeholders.append(f"`{raw_col}` = %s") # 动态转义列名
437
+ set_params.append(dict_data[raw_col])
438
+ change_col.append(raw_col)
434
439
 
440
+ if change_placeholders:
441
+ full_params = set_params + condition_params
435
442
  sql = f"""UPDATE `{table_name}`
436
- SET {','.join(set_parts)}
437
- WHERE {' AND '.join(condition_parts)}"""
443
+ SET {','.join(change_placeholders)}
444
+ WHERE {' AND '.join(condition_parts)}"""
438
445
  cursor.execute(sql, full_params)
439
446
  else: # 没有数据返回,则直接插入数据
440
447
  # 参数化插入语句
@@ -524,7 +531,7 @@ class MysqlUpload:
524
531
  [pd.to_numeric(df[col], errors='ignore') for col in df.columns.tolist()]
525
532
  dtypes = df.dtypes.to_dict()
526
533
  __res_dict = {}
527
- for k, v in dtypes.items():
534
+ for k, v in dtypes.copy().items():
528
535
  result1 = re.findall(r'编码|_?id|货号|款号|文件大小', k, re.IGNORECASE)
529
536
  result2 = re.findall(r'占比$|投产$|产出$|roi$|率$', k, re.IGNORECASE)
530
537
  result3 = re.findall(r'同比$|环比$', k, re.IGNORECASE)
@@ -611,7 +618,7 @@ class MysqlUpload:
611
618
  dtypes, df = self.convert_df_dtypes(df)
612
619
  if set_typ:
613
620
  # 更新自定义的列数据类型
614
- for k, v in dtypes.items():
621
+ for k, v in dtypes.copy().items():
615
622
  # 确保传进来的 set_typ 键存在于实际的 df 列才 update
616
623
  [dtypes.update({k: inside_v}) for inside_k, inside_v in set_typ.items() if k == inside_k]
617
624
 
@@ -635,7 +642,7 @@ class MysqlUpload:
635
642
  with connection.cursor() as cursor:
636
643
  # 1. 查询表, 不存在则创建一个空表
637
644
  sql = "SHOW TABLES LIKE %s;" # 有特殊字符不需转义
638
- cursor.execute(sql, (table_name))
645
+ cursor.execute(sql, (table_name,))
639
646
  if not cursor.fetchone():
640
647
  create_table_sql = f"CREATE TABLE IF NOT EXISTS `{table_name}` (id INT AUTO_INCREMENT PRIMARY KEY)"
641
648
  cursor.execute(create_table_sql)
@@ -661,7 +668,7 @@ class MysqlUpload:
661
668
  # 创建索引
662
669
  if col == '日期':
663
670
  sql = f"SHOW INDEXES FROM `{table_name}` WHERE `Column_name` = %s"
664
- cursor.execute(sql, (col))
671
+ cursor.execute(sql, (col,))
665
672
  result = cursor.fetchone() # 检查索引是否存在
666
673
  if not result:
667
674
  cursor.execute(f"CREATE INDEX index_name ON `{table_name}`(`{col}`)")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mdbq
3
- Version: 3.8.14
3
+ Version: 3.8.16
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -1,13 +1,13 @@
1
1
  mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
2
- mdbq/__version__.py,sha256=5G-_mHmo-5FjfAe99IHqW_10kybGnZlf2oRqK_oW9UA,18
2
+ mdbq/__version__.py,sha256=VUh6syxyz3BeTHjQrrlUgLdyX1-2SRQdP5locYySmCQ,18
3
3
  mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
4
- mdbq/aggregation/query_data.py,sha256=xJ4YeShUGEpYqEKO0HKqfD7nT6AEUEujVb_3Ea_QTBw,179995
4
+ mdbq/aggregation/query_data.py,sha256=5_OzjGR5Sq00q-EgAYmSE5V9i4Solw9y4hkldl4mvt8,179808
5
5
  mdbq/config/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
6
6
  mdbq/config/config.py,sha256=eaTfrfXQ65xLqjr5I8-HkZd_jEY1JkGinEgv3TSLeoQ,3170
7
7
  mdbq/log/__init__.py,sha256=Mpbrav0s0ifLL7lVDAuePEi1hJKiSHhxcv1byBKDl5E,15
8
8
  mdbq/log/spider_logging.py,sha256=-ozWWEGm3HVv604ozs_OOvVwumjokmUPwbaodesUrPY,1664
9
9
  mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
10
- mdbq/mysql/mysql.py,sha256=zYIpxKJWrb4PS13a51n4gTSTn2rRfzAB-yWDoJL49y8,55802
10
+ mdbq/mysql/mysql.py,sha256=4N6srlRYomoSHdK4Y84fxkIW_eL5xFkb3Jo06sebSi0,55031
11
11
  mdbq/mysql/s_query.py,sha256=X055aLRAgxVvueXx4NbfNjp6MyBI02_XBb1pTKw09L0,8660
12
12
  mdbq/other/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
13
13
  mdbq/other/download_sku_picture.py,sha256=YU8DxKMXbdeE1OOKEA848WVp62jYHw5O4tXTjUdq9H0,44832
@@ -21,7 +21,7 @@ mdbq/redis/__init__.py,sha256=YtgBlVSMDphtpwYX248wGge1x-Ex_mMufz4-8W0XRmA,12
21
21
  mdbq/redis/getredis.py,sha256=Uk8-cOWT0JU1qRyIVqdbYokSLvkDIAfcokmYj1ebw8k,24104
22
22
  mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
23
23
  mdbq/spider/aikucun.py,sha256=m7ZIvrc9pqoGCYEH3FtgKTwqhX7QB6qzgc2twDzhX4w,19962
24
- mdbq-3.8.14.dist-info/METADATA,sha256=huDrR4rNqxqoau4lxivHl6AOxG7kpiG5a2rUrTK9Tfo,364
25
- mdbq-3.8.14.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
26
- mdbq-3.8.14.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
27
- mdbq-3.8.14.dist-info/RECORD,,
24
+ mdbq-3.8.16.dist-info/METADATA,sha256=TS9KZw82-cE9gTPtfKSLzhwWzda-8ZnZ6384Vm0xU4I,364
25
+ mdbq-3.8.16.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
26
+ mdbq-3.8.16.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
27
+ mdbq-3.8.16.dist-info/RECORD,,
File without changes